diff --git a/xactmon/certificate.yaml b/xactmon/certificate.yaml new file mode 100644 index 0000000..f454f9c --- /dev/null +++ b/xactmon/certificate.yaml @@ -0,0 +1,21 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: rabbitmq +spec: + secretName: rabbitmq-cert + commonName: xactmon + issuerRef: + group: cert-manager.io + kind: ClusterIssuer + name: rabbitmq-ca + privateKey: + algorithm: ECDSA + rotationPolicy: Always + keystores: + pkcs12: + create: true + profile: Modern2023 + passwordSecretRef: + name: rabbitmq-cert-password + key: password diff --git a/xactmon/commerce.awk b/xactmon/commerce.awk new file mode 100644 index 0000000..d348a70 --- /dev/null +++ b/xactmon/commerce.awk @@ -0,0 +1,22 @@ +/ending in/ { + gsub(/^ +/, ""); + account=$0 +} + +/•/ { + if (date=="") { + gsub(/[^0-9-]+/, ""); + date=$0 + } else if (description == "") { + gsub(/.*• /, "") + description=$0 + } else if (amount == "") { + gsub(/[^0-9.]+/, ""); + amount=$0 + } +} + +END { + OFS="|" + print(account, date, amount, description) +} diff --git a/xactmon/config.toml b/xactmon/config.toml new file mode 100644 index 0000000..edb14da --- /dev/null +++ b/xactmon/config.toml @@ -0,0 +1,16 @@ +processor_rules = "/etc/xactmon/rules.toml" + +[jmap] +url = "https://api.fastmail.com" +token_file = "/run/secrets/xactmon/fastmail.token" + +[amqp] +url = "amqps://xactmon@rabbitmq.pyrocufflink.blue?auth_mechanism=external" +clientcert = "/run/secrets/rabbitmq/cert/keystore.p12" +clientcert_password = "/run/secrets/rabbitmq/password" +cacert = "/run/dch-ca/dch-root-ca.crt" + +[firefly] +url = "https://firefly.pyrocufflink.blue" +token_file = "/run/secrets/xactmon/firefly.token" +error_if_duplicate_hash = false diff --git a/xactmon/kustomization.yaml b/xactmon/kustomization.yaml new file mode 100644 index 0000000..30f6b77 --- /dev/null +++ b/xactmon/kustomization.yaml @@ -0,0 +1,27 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: xactmon + +labels: +- pairs: + app.kubernetes.io/instance: xactmon + app.kubernetes.io/part-of: xactmon + +resources: +- namespace.yaml +- secrets.yaml +- xactmon.yaml +- certificate.yaml +- ../dch-root-ca + +configMapGenerator: +- name: xactmon + files: + - config.toml + - rules.toml + - commerce.awk + +images: +- name: git.pyrocufflink.net/packages/xactmon + newTag: dev diff --git a/xactmon/namespace.yaml b/xactmon/namespace.yaml new file mode 100644 index 0000000..78c1607 --- /dev/null +++ b/xactmon/namespace.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: xactmon + labels: + app.kubernetes.io/component: xactmon + app.kubernetes.io/name: xactmon diff --git a/xactmon/rules.toml b/xactmon/rules.toml new file mode 100644 index 0000000..1209b5a --- /dev/null +++ b/xactmon/rules.toml @@ -0,0 +1,19 @@ +[[rule]] +name = "Commerce Bank" +match = "commercebankalerts@commercebank.com" +date_fmt = "%m-%d-%Y" +awk_script = "/etc/xactmon/commerce.awk" + +[[rule]] +name = "Chase (Amazon Rewards) Visa" +match = "no.reply.alerts@chase.com" +date_fmt = "%b %d, %Y at %-I:%M %p" +regex = 'Account\s*(?P.+)\n\s*Date\s+(?P.+[AP]M).*\n\s*Merchant\s+(?P.+)\n\s*Amount\s+\$(?P[0-9]+\.[0-9]{2})' + +[[rule]] +name = "HSA Bank" +match = "hsabank.com" +date_fmt = "%m/%d/%Y" +account = "HSA Bank HSA" +default_description = "Debit Card Purchase" +regex = '\$(?P[0-9]+\.[0-9]{2}) on (?P[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}).' diff --git a/xactmon/secrets.yaml b/xactmon/secrets.yaml new file mode 100644 index 0000000..4d06153 --- /dev/null +++ b/xactmon/secrets.yaml @@ -0,0 +1,55 @@ +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + name: rabbitmq-cert-password + namespace: xactmon + labels: + app.kubernetes.io/name: xactmon + app.kubernetes.io/component: xactmon +spec: + encryptedData: + password: AgCblkGzJTe+UaKxD9fGRPidDlULnhoqJ8Xvp0Cyl7jNx9Yky2B3SVrC48aCgTNUcRTAahzXCJ8jNUefVbN/x87z/Dim6PepZsP0lBI5qhdW9SZnlrwInObbaCiHWp1SU/WFyxxU4asxWvPArdzfEAe2/V1eulC7kWjNRGXemfbWhY/qL/5jBJhgoD/0xENEa1OxRqDo3EpqFlgKWGm9Sr9F1V+PpksZCgZkXfI/V3Y2v5s9z0s+Ylc444kwvLjkK5dmXh1FnqjK/ZeXwjZUXg+cjZGVy5bNJYlhxRURY1DT0BAvShTJCCH2RajmbV2rZf90v65TcNHyURGA9jKXmFd+x7J9C0jdnN2bhmWWreQlfXB6WZCoU+G1t06nNVIOeS8p5BIByvenWCwqklnHYCzUxu0PEN86dTqSGWD9r8Y4VE94PZQ+wO+MmGEn9y+CUNKJ5apoP3AhpW0rliShUAEjQnyOOekgPYETNSwvb9IkKiueXc3NztQNch39X97kVsqVkknpay2GdxcuCdDZLqFoUpzyhaJo7QQxhZBiN1oW2Wy+m+CIM1gzi0U2f91Gz53/ozhlGD92QZqhd55MwGI4sANyyIo4TRxgV//VKDA/uIpJcDe0jnGxxbvg5qLHqSl+87jaTA6h1cUWAyVrzX5dJgjthc6h25Azne6YZHIItY17Hul2eLcEGAmdvu6dYWJ6SzYC46W997ndtdClhBwV + template: + metadata: + name: rabbitmq-cert-password + namespace: xactmon + labels: + app.kubernetes.io/name: xactmon + app.kubernetes.io/component: xactmon + +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + name: xactmon + namespace: xactmon + labels: + app.kubernetes.io/name: xactmon + app.kubernetes.io/component: xactmon +spec: + encryptedData: + fastmail.token: AgB7GUTJ4QqkLDUy2DePEb3OLtKNik6xw46oe2WA0HC37CEG02KREFK4vJFcbUAwkqpGO51FYWq1JmvKxzIse9265N98Dl1D0w9AVLKBBuSAT915DK6W8ya9zVLgYlPBnhlBZzwRjwSN3i5dREbvIGtmnZseZYgXCWuE1JRGbd/HXDOnPSq98rM/XtDUZ+p8x40LpC1rYAVmTHrDoLOHM1Gyt6X6jR6jifWtmOXoPFE4VDdidaIhmHa7mJoboHuaH+8QSlCrwqw6aG5EVJ1GzKbCaWiVjSgGFLVJjHJRJHUQTa48vlDhMlPOgSQ5ur2VMuBaw+9FpjVukL4pT/GCNAAXpotkx/EQg3iVJsboC3D5Xt5P92KbJpZrzH8EHZg5mLNz7rUOcj4Q5LHdECmlrOsLLXAWtc2u0eTo/28V8ZaZZgORWCbsHom8ziaS2txMQP3S2uUIH7g67kRLuD91nw/n3sCaxrJtDsHnvvLkanCdooPPzyMRrVqu0OP4nbzWeCoziI8JLjp++RZ56Ztzik9PtpqHnJERedShH/GXD0P5B7oTPf1qbv3Z3w4N/ujXSmIxK0RvwBDqgzfzyRHQkzxq4EK4Y98KKEjQHM5bgD3lreuIw+mSvBS4qoZGse4LkCMNOdcm0qDGeVnhbE54a36USqpPte1dxyvrL61vaT7HZDTVV0ib8c/YJ3sYz8jrt9By7cXtjyVWD0j+m2Jb22ZrqvnwpW5mgC3O+C2maRTuaZd8s8E2Qr0RM4mPUA+jXHP4mBPhGDkO2x378vFUA/u9OPToTDSYl6H9ZaLvyITWhs4= + firefly.token: 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 + template: + metadata: + name: xactmon + namespace: xactmon + labels: + app.kubernetes.io/name: xactmon + app.kubernetes.io/component: xactmon + +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + name: imagepull-gitea + namespace: xactmon +spec: + encryptedData: + .dockerconfigjson: AgCrayJ/+8ndjOvkl/zocR4KAkVd1e7Pab48ngQS1ePwj6PA3xuLaL4xacS2QUoGyNrh4ATdsH4mw7dscVFDTFd7UWiQuA+Xx4tFcPX+NNd31QPp+MgdZtmbmBAPQEf5eiIXEsuQB++TP/EuOgS1pSKPH40LJOsNHqGwCZ+l/tQs/Ll+fZ4VqaiSALMGrJICeCO3k7Gzz03glqVu2oKxIzKqoYrv0+G+UWqaDCyJsjoT5KYs2nJOm/ArbqrUQJBqdjKf4QO07krZcSPHrw9a49VGnfx6ILifUJJ/xw4hbqNt7rmuFknfALDtHj1z0vY5ZX+45NcXjRF+9JZd/2McjgEtHWaOE6GHKG//nciNWbWXwmLZ/+2tphBa9pg6FiNSQhepKGTLQYNmkHbcTevvqW6e7bFA7QmV6yXZ/u2WwKvXtgZUVCmpD9qnltJtI/oiFKnkle4Y/lOtSN/fTo7uI8YT5u+qEtKJEwv0Txe2rFL74xzjC9eaI6ehniksk1CMlVTi66Y4AvbZSzGYGwbMvUfl62hzLPSogORxGcHcql6HCcsdXfwQU6etmVba29ZS7CkB/+pfu4UO43mnnT33KXIzZknTiQKruAzGKLCN/nHGBilTNYWiTTPCje3WhLMnfzJ58w99ncK4yAOg8xk/qekWoyJNSofAc4VVruaHgHXh0QC8NX5jhzQkrk/fAtPd8U3GLXV5xflpwL2M/liVHkoQNIJc9n7tuCNTYFcu58pC5Zxqpi0PNkm9PUxDYjRfIDE9TcHnMK3ma4REA5aGYokzljv28qxC0X7WKkZ4cpYMAvFQ1Ipq8EeSdBUiE8pTTkBZ2J1JwsqepcwYt/w3+5wRd3tFf5BOLxEiXC5nM8KubnoWXaSszyDNVhRqtGxuzqrWdhhT5iJXd2aiiMKJxnsCzNcQKpo0UP+s9utzCDMFxKkVGeld/FZhv5SUkUugwexvjX7zfcOPX0C841P5uDu2saZFJR1oaNwPnku5yVPvrn6AYGxaZQvjol6/qgI= + template: + metadata: + name: imagepull-gitea + namespace: xactmon + type: kubernetes.io/dockerconfigjson diff --git a/xactmon/xactmon.yaml b/xactmon/xactmon.yaml new file mode 100644 index 0000000..3e7e2cd --- /dev/null +++ b/xactmon/xactmon.yaml @@ -0,0 +1,238 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: xactmon-receiver-jmap + labels: + app.kubernetes.io/name: xactmon-receiver-jmap + app.kubernetes.io/component: receiver-jmap +spec: + selector: + matchLabels: + app.kubernetes.io/name: xactmon-receiver-jmap + app.kubernetes.io/component: receiver-jmap + template: + metadata: + labels: + app.kubernetes.io/name: xactmon-receiver-jmap + app.kubernetes.io/component: receiver-jmap + spec: + containers: + - name: receiver-jmap + image: git.pyrocufflink.net/packages/xactmon + imagePullPolicy: Always + args: + - receiver-jmap + - /etc/xactmon/config.toml + env: + - name: RUST_LOG + value: xactmon=trace,info + - name: TZ + value: America/Chicago + volumeMounts: + - mountPath: /etc/xactmon + name: xactmon-config + readOnly: true + - mountPath: /run/dch-ca + name: dch-ca + readOnly: true + - mountPath: /run/secrets/xactmon + name: xactmon-secrets + readOnly: true + - mountPath: /run/secrets/rabbitmq/password + name: rabbitmq-cert-password + subPath: password + readOnly: true + - mountPath: /run/secrets/rabbitmq/cert + name: rabbitmq-cert + readOnly: true + - mountPath: /tmp + name: tmp + subPath: tmp + imagePullSecrets: + - name: imagepull-gitea + securityContext: + runAsUser: 251 + runAsGroup: 251 + fsGroup: 251 + volumes: + - name: dch-ca + configMap: + name: dch-root-ca + - name: rabbitmq-cert + secret: + secretName: rabbitmq-cert + defaultMode: 0440 + - name: rabbitmq-cert-password + secret: + secretName: rabbitmq-cert-password + defaultMode: 0440 + - name: tmp + emptyDir: + medium: Memory + - name: xactmon-config + configMap: + name: xactmon + - name: xactmon-secrets + secret: + secretName: xactmon + defaultMode: 0440 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: xactmon-processor + labels: + app.kubernetes.io/name: xactmon-processor + app.kubernetes.io/component: processor +spec: + selector: + matchLabels: + app.kubernetes.io/name: xactmon-processor + app.kubernetes.io/component: processor + template: + metadata: + labels: + app.kubernetes.io/name: xactmon-processor + app.kubernetes.io/component: processor + spec: + containers: + - name: processor + image: git.pyrocufflink.net/packages/xactmon + imagePullPolicy: Always + args: + - processor + - /etc/xactmon/config.toml + env: + - name: RUST_LOG + value: xactmon=trace,info + - name: TZ + value: America/Chicago + volumeMounts: + - mountPath: /etc/xactmon + name: xactmon-config + readOnly: true + - mountPath: /run/dch-ca + name: dch-ca + readOnly: true + - mountPath: /run/secrets/xactmon + name: xactmon-secrets + readOnly: true + - mountPath: /run/secrets/rabbitmq/password + name: rabbitmq-cert-password + subPath: password + readOnly: true + - mountPath: /run/secrets/rabbitmq/cert + name: rabbitmq-cert + readOnly: true + - mountPath: /tmp + name: tmp + subPath: tmp + imagePullSecrets: + - name: imagepull-gitea + securityContext: + runAsUser: 251 + runAsGroup: 251 + fsGroup: 251 + volumes: + - name: dch-ca + configMap: + name: dch-root-ca + - name: rabbitmq-cert + secret: + secretName: rabbitmq-cert + defaultMode: 0440 + - name: rabbitmq-cert-password + secret: + secretName: rabbitmq-cert-password + defaultMode: 0440 + - name: tmp + emptyDir: + medium: Memory + - name: xactmon-config + configMap: + name: xactmon + - name: xactmon-secrets + secret: + secretName: xactmon + defaultMode: 0440 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: xactmon-importer-firefly + labels: + app.kubernetes.io/name: xactmon-importer-firefly + app.kubernetes.io/component: importer-firefly +spec: + selector: + matchLabels: + app.kubernetes.io/name: xactmon-importer-firefly + app.kubernetes.io/component: importer-firefly + template: + metadata: + labels: + app.kubernetes.io/name: xactmon-importer-firefly + app.kubernetes.io/component: importer-firefly + spec: + containers: + - name: importer-firefly + image: git.pyrocufflink.net/packages/xactmon + imagePullPolicy: Always + args: + - importer-firefly + - /etc/xactmon/config.toml + env: + - name: RUST_LOG + value: xactmon=trace,info + - name: TZ + value: America/Chicago + volumeMounts: + - mountPath: /etc/xactmon + name: xactmon-config + readOnly: true + - mountPath: /run/dch-ca + name: dch-ca + readOnly: true + - mountPath: /run/secrets/xactmon + name: xactmon-secrets + readOnly: true + - mountPath: /run/secrets/rabbitmq/password + name: rabbitmq-cert-password + subPath: password + readOnly: true + - mountPath: /run/secrets/rabbitmq/cert + name: rabbitmq-cert + readOnly: true + - mountPath: /tmp + name: tmp + subPath: tmp + imagePullSecrets: + - name: imagepull-gitea + securityContext: + runAsUser: 251 + runAsGroup: 251 + fsGroup: 251 + volumes: + - name: dch-ca + configMap: + name: dch-root-ca + - name: rabbitmq-cert + secret: + secretName: rabbitmq-cert + defaultMode: 0440 + - name: rabbitmq-cert-password + secret: + secretName: rabbitmq-cert-password + defaultMode: 0440 + - name: tmp + emptyDir: + medium: Memory + - name: xactmon-config + configMap: + name: xactmon + - name: xactmon-secrets + secret: + secretName: xactmon + defaultMode: 0440