Add new infra architecture

This commit is contained in:
Urtzi Alfaro
2026-01-19 11:55:17 +01:00
parent 21d35ea92b
commit 35f164f0cd
311 changed files with 13241 additions and 3700 deletions

View File

@@ -0,0 +1,179 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: bakery-ia
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
app.kubernetes.io/part-of: bakery-ia
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
template:
metadata:
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
spec:
imagePullSecrets:
- name: dockerhub-creds
securityContext:
fsGroup: 999 # redis group
initContainers:
- name: fix-tls-permissions
image: busybox:1.36
securityContext:
runAsUser: 0
command: ['sh', '-c']
args:
- |
cp /tls-source/* /tls/
chmod 600 /tls/redis-key.pem
chmod 644 /tls/redis-cert.pem /tls/ca-cert.pem
chown 999:999 /tls/*
ls -la /tls/
volumeMounts:
- name: tls-certs-source
mountPath: /tls-source
readOnly: true
- name: tls-certs-writable
mountPath: /tls
containers:
- name: redis
image: redis:7.4-alpine
ports:
- containerPort: 6379
name: redis-tls
- containerPort: 6380
name: redis-plain
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secrets
key: REDIS_PASSWORD
command:
- redis-server
- --appendonly
- "yes"
- --requirepass
- $(REDIS_PASSWORD)
- --maxmemory
- "512mb"
- --databases
- "16"
# TLS port for external/secure connections
- --tls-port
- "6379"
# Plain TCP port for internal cluster services (Mailu)
- --port
- "6380"
- --tls-cert-file
- /tls/redis-cert.pem
- --tls-key-file
- /tls/redis-key.pem
- --tls-ca-cert-file
- /tls/ca-cert.pem
- --tls-auth-clients
- "no"
volumeMounts:
- name: redis-data
mountPath: /data
- name: tls-certs-writable
mountPath: /tls
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
exec:
command:
- redis-cli
- --tls
- --cert
- /tls/redis-cert.pem
- --key
- /tls/redis-key.pem
- --cacert
- /tls/ca-cert.pem
- -a
- $(REDIS_PASSWORD)
- ping
initialDelaySeconds: 30
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 3
readinessProbe:
exec:
command:
- redis-cli
- --tls
- --cert
- /tls/redis-cert.pem
- --key
- /tls/redis-key.pem
- --cacert
- /tls/ca-cert.pem
- -a
- $(REDIS_PASSWORD)
- ping
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 5
failureThreshold: 3
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-pvc
- name: tls-certs-source
secret:
secretName: redis-tls-secret
- name: tls-certs-writable
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: bakery-ia
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
spec:
type: ClusterIP
ports:
- port: 6379
targetPort: 6379
protocol: TCP
name: redis-tls
- port: 6380
targetPort: 6380
protocol: TCP
name: redis-plain
selector:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
namespace: bakery-ia
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/component: cache
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,25 @@
apiVersion: v1
kind: Secret
metadata:
name: redis-tls-secret
namespace: bakery-ia
labels:
app.kubernetes.io/name: bakery-ia
app.kubernetes.io/component: redis-tls
type: Opaque
data:
# Redis TLS certificates (base64 encoded)
# Generated using infrastructure/tls/generate-certificates.sh
# Valid for 3 years from generation date
#
# Certificate details:
# Subject: CN=redis-service.bakery-ia.svc.cluster.local, O=BakeryIA, OU=Cache
# Issuer: CN=BakeryIA-CA, O=BakeryIA, OU=Security
#
# To regenerate:
# 1. Run: infrastructure/tls/generate-certificates.sh
# 2. Run: scripts/create-tls-secrets.sh
ca-cert.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZ5ekNDQTdPZ0F3SUJBZ0lVUGdPcU5ZK1pvS0J5UTFNZk84bGtpR2hPbXhJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2RURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2tOaGJHbG1iM0p1YVdFeEZUQVRCZ05WQkFjTQpERk5oYmtaeVlXNWphWE5qYnpFUk1BOEdBMVVFQ2d3SVFtRnJaWEo1U1VFeEVUQVBCZ05WQkFzTUNGTmxZM1Z5CmFYUjVNUlF3RWdZRFZRUUREQXRDWVd0bGNubEpRUzFEUVRBZUZ3MHlOVEV3TVRneE5ESXlNVFJhRncwek5URXcKTVRZeE5ESXlNVFJhTUhVeEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlEQXBEWVd4cFptOXlibWxoTVJVdwpFd1lEVlFRSERBeFRZVzVHY21GdVkybHpZMjh4RVRBUEJnTlZCQW9NQ0VKaGEyVnllVWxCTVJFd0R3WURWUVFMCkRBaFRaV04xY21sMGVURVVNQklHQTFVRUF3d0xRbUZyWlhKNVNVRXRRMEV3Z2dJaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUURSRDVPMmVna1lnOUhOUlI1U1UwYkxuR0hqcHYvUmFnck03ZGh1c2FXbgpyZkRGNVZwVFo0czkvOXNPRUowTnlqdW9LWGFtb3VUd1IxbncxOUZkSDhmMWVvbWNRNGVLdzJIa3hveHFSMzR0ClJEYUFHejNiV08rcmFUUTRTeU1LN1hGTW92VVVpTGwrR08yM2wxQk5QZmh6a2NEa1o5N200MzRmMVFWbzk5dGIKaFY0YklMYW9GSXFmMDlNMEUxL2ZhQitKQ1I4WWtsN0xvWGd1ejNWUi9CVW5kMHZNc1RNV3VlRC8yblZ1VVpPMAowcFVtVFVCUTJRZDc2NTdrL0hXZC8xd2NFQUw5ZFhOUmJ4aEROZkdnYzNXdFFoZ2djcFlMUWFmTGE4MXRseHljCndEZ042UGRFbFVseGdYL091b1oxeWxNWkU3eHBzTXRwbjFBd2VvZFZibTNRcDVBMXlkeWJFNjF1MXVyWXoxTHQKV05aOWVPZkFxZXdpWVFIVlpXTUM0YTRTYSsyeU02cTVQWC80ZytUYklUaDhoWkp3WFBLNUVEaWc3dkYxNEpQbApsRVJOcHdpYTNuNmEwUDcwM0hQTjZya1FPNWtWVGRpVXNmaWJNdGNVSkhMeVdXUUFSQm15ZVZma0lDYWFlWUVsCkVMa3N3YTlOVkVTS3ZRYUhLU2lIWkZoRUkwYUF2Y3BBam0xRU9oRWEraFNSaE9vRnlVT3ZHK2NNT2ZjQlNtTDAKVW1sRC9sZmFuVFQwems1YXFzcEVrWEdlQnczMXJtWi8wQVpPalYycHBSeFdXZWt6bzlCZjdnNmVMVFk0VUNDNQpNeVB0em14OVRiWHJOQW5YaGlGNkxnNWgyOFI0MkdUZTVBZDZUSGtGOVMvS2hxOHUwZFk1U0EyR1VGMUViUU84Ckt3SURBUUFCbzFNd1VUQWRCZ05WSFE0RUZnUVVBKzZxL2tjOGZUUVUxRURxekdSZktRcHE2bTB3SHdZRFZSMGoKQkJnd0ZvQVVBKzZxL2tjOGZUUVUxRURxekdSZktRcHE2bTB3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVF1dkZoMitIUUZ5OFZUY1VnYWxFVmlheXQxelFHdjRySVNtaXEzRzZJZVhQClhTNGd3cUhrRnpUd1p2bW9oVHdtT0N3Vy94RjRLZ3htRmJ5V05yRUpKRXFjYmVkcVVXVi8wQkNhRm1KdlVkZEkKK2V4L2lEM0ZlYnU4QUZJK0o4bEJIL0NlbkRpU0xIaGd5c2VZOHV3Um5Yc3NoWDVSbkRpckYxdUtyMUo2MzVhbgpHbHlGSU5Vcm5RbGd1RXZ0cjBlbkdVbHpUNXJXajR5MEFXVWRiWGk4dlJzaldvUThKYTBCeFRyWVloL2tPL0ZJClB0cVg3d3N4b0pNREVRNzF6aHdhN1dMUWMyZGZiMnJBcjF1QmgzcU53aVZCSU5CK3QzSkZ2NzJ4cXNXZ3VySUIKSWYyc29SVEkybk1lNWdURzFEZmQrVjI0amZhL3lJZ0FzTWpDem1HUUsyMHZvYlg0c0FWbm1QVmJaZzlTTEZaaQpNaWRrbjlPOVU2OE1FT2UzSWFzY2xkN2ZwNUprK0hyYkpVNi9zMTZFRVIvQWdEM09vajN3UmdqVENTK0FERCtqCnhvMk84Vlgya1BvMDNBTitpWWEzbkptbE1GekNyelQrOFp4U25QNUZxR2cyRUNFYnFxQTBCLzVuYVZwbWRZYVYKNDFvRkxzd2NGbTJpcUdhd2JzTE45eDN0dklDdUU5M0hZazFqNzJQelhhaVNMdHB2YW1IMWRSWUMrSFVNMUwwTwo0OUNOTVlKZUwvTmx5UXVaSm0yWDBxRE5TWG1STUw4SFU5c093V1g2cFBQSk96dXF0Z2R4Lytsa0dBZDJ3WkpVCklWYm1MNlF2emRidGEvY1NWd3NMdEJ6RzQ4YTFiNEtCYzdXTEhUd2JyZEJSVGcwVGtMWTRrdkNaZTVuTmw0RT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
redis-cert.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUdjekNDQkZ1Z0F3SUJBZ0lVRytCME0ycnhucWpHZHRmbzBCaGV2S0N4MGY4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd2RURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2tOaGJHbG1iM0p1YVdFeEZUQVRCZ05WQkFjTQpERk5oYmtaeVlXNWphWE5qYnpFUk1BOEdBMVVFQ2d3SVFtRnJaWEo1U1VFeEVUQVBCZ05WQkFzTUNGTmxZM1Z5CmFYUjVNUlF3RWdZRFZRUUREQXRDWVd0bGNubEpRUzFEUVRBZUZ3MHlOVEV3TVRneE5ESXlNVFJhRncweU9ERXcKTVRjeE5ESXlNVFJhTUlHUU1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQXdLUTJGc2FXWnZjbTVwWVRFVgpNQk1HQTFVRUJ3d01VMkZ1Um5KaGJtTnBjMk52TVJFd0R3WURWUVFLREFoQ1lXdGxjbmxKUVRFT01Bd0dBMVVFCkN3d0ZRMkZqYUdVeE1qQXdCZ05WQkFNTUtYSmxaR2x6TFhObGNuWnBZMlV1WW1GclpYSjVMV2xoTG5OMll5NWoKYkhWemRHVnlMbXh2WTJGc01JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBdnNhMgo1MUdFR0VuaW81NHUxdGtNeFNCTGQ4Mm9ML3VsYWIxYXdxREJqcUJkVUFpZzJsMWpScFFyNUxHNVh3UzVoNzM5ClkrdnlQbFpWZW16dVRiNmszbjhPckxNcnUvUFBSRytpUWc3cXlUR1orYmF3YWY2YVhFZUNLOEExWW5xSy9ONEsKQTFIUkxXRXNXRzBKQ2VZakZPZnFzempWTEtydFJhSDd6S2lBREZxREJCbXhScWsvUDJvSjZmK1hXaWpwNE5KdQpPaVdoQmNoYmpjRi9mTTZ2MGVsQlMvOGs1cHVpOGtFdWRNZWExSVFLNXFTSll3TjZZNXRNT3BKcm1IdTFFN05vCkJRZWduakJvMWJaUkFkMWgrL2NxOHAwWWt3amE5dTJnSk5jczMxcWY4MUFtNitxNklXMExqTHFUMnlINVU1aW8KS2hTa0FuczNwcUFPNFZrSWRuM3l0Y2tkK00wQmNNcTRKQm5iYk0vZ1ZPV3I1RXorSERKOWsyckFSbzBWWFB5cQpnT1JxMnNXU2N0eVFiV0pPdExOUWVVbUN0dXZ4d0RyVVNoQWlYZGhhM3ptejdYOWJiNCtWUXA2elJaM3h2bXBnCnFFeG1Pc05zMDBMak9sMHBsalVmR0ZBR2Rmb21JSXpSWmxnVkN6TVVsWkQ0cGNQVnNhSGJuR1ovNi9ZbXhNZGUKOUxjbjRrYmlrNjVmZEFJbnhmVFAySU1NZER3TUZkYkZpcy9SbDIwZWo3QUJ0YTNLdVhvZFluMXkwbitYTFIyTAo3YWJUcW9xSXRnUW1BY2lITlBVYWNnREMvbFBRSk95ckRaVTloQ3NMdDJJVVZKTUN6U2QzR3JDQzA4d2dSb2U1CjZRNUh0NEUyWG5kV3NlWWZxVnRRM2c4WktDaVUrUU1JQmt4SzdHOENBd0VBQWFPQjNqQ0IyekFMQmdOVkhROEUKQkFNQ0JEQXdIUVlEVlIwbEJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUcwR0ExVWRFUVJtTUdTQwpLWEpsWkdsekxYTmxjblpwWTJVdVltRnJaWEo1TFdsaExuTjJZeTVqYkhWemRHVnlMbXh2WTJGc2doZHlaV1JwCmN5MXpaWEoyYVdObExtSmhhMlZ5ZVMxcFlZSU5jbVZrYVhNdGMyVnlkbWxqWllJSmJHOWpZV3hvYjNOMGh3Ui8KQUFBQk1CMEdBMVVkRGdRV0JCU2RJV1V6Q2gvNE9SZmJLR2JYTVJ2eXhXTFdyekFmQmdOVkhTTUVHREFXZ0JRRAo3cXIrUnp4OU5CVFVRT3JNWkY4cENtcnFiVEFOQmdrcWhraUc5dzBCQVFzRkFBT0NBZ0VBaEd2cFBSSlpqQkZpCnBaNDNVaFVGTGFIeCtRMHZncy96eXlxVzVqSys3ZWZwY3Z0Sk9CbXVrRUtMaXUwWGFrZit5VDhWRlp4R2tzZkYKcVZyL1Vvb2x3bTVEamlHOE9FT29PYTJCZTlqb0dTdmI3c0JzZ24wYS9pdElGUnpEUXdadGJQZmdpMGFndkJmTQpxczFCNm9IempBMkdSNmlMUDFXYzg4VXRNWFJwV1c0VnZSclZIallzWHVuM2ZHdGYxR1J3ZndBWFFJNys5YldpClNPQ2hEOWVJNk1xdUNYQmRCQVgvQ3FueGs4aHVia3dXY3NIeVNGQkRMcVFoUHM1dU04bGkzK01QZ3BMWENmYVkKWDYvWnpIM05nSjNEK1BJSDU5WllwaEczenZsRnBHRDRvRzNRMkFvbHhxd01SMytQNmM5SWYxRGZNTW9TZ1YzKwptZnZnUmpONXRuZ0IrL29CaXVtYk00K0VGOGFNUmsxR095V3BmM2VSZkc1NStPVEpsTHNEWE9TQlcrSzFOQ3o0CnlOWVR5c2h3eGpWU1BYcWZhdGVBWnpDNVNqRk1SZHJkSEQxME0wZ2w1L2RYY3AreDVocFFTWTNNK2dNMndXZEkKem83SkJPdDlRMUZRRGdUM2pJVldRNVB0TmhkOW9UOVdkYzBFZEppenlObDN2aTltMi9iSktWcEhPMnltZG5IWQpoUG12UVlWdGZzTWxOdmtzdkRMcFhlbUc3czR2akhmMTJZRVA4VFQ1REpnRDQ2TlZvZTM5S2E0N0lmYVRXdWdOCkZXb1YvUGFqUkl4L0lPL2tPcDROQnBlQjY5TytudVlVVU5jQ3cwZmlsQSttRmdXUWpxRkdQK2ZxV05hSmorcFAKNTByelBOc3hwK3FpdzZGVm9aNTVjY3hFMjdrbnZlWT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
redis-key.pem: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Nzd2dna25BZ0VBQW9JQ0FRQyt4cmJuVVlRWVNlS2oKbmk3VzJRekZJRXQzemFndis2VnB2VnJDb01HT29GMVFDS0RhWFdOR2xDdmtzYmxmQkxtSHZmMWo2L0krVmxWNgpiTzVOdnFUZWZ3NnNzeXU3ODg5RWI2SkNEdXJKTVpuNXRyQnAvcHBjUjRJcndEVmllb3I4M2dvRFVkRXRZU3hZCmJRa0o1aU1VNStxek9OVXNxdTFGb2Z2TXFJQU1Xb01FR2JGR3FUOC9hZ25wLzVkYUtPbmcwbTQ2SmFFRnlGdU4Kd1g5OHpxL1I2VUZML3lUbW02THlRUzUweDVyVWhBcm1wSWxqQTNwam0wdzZrbXVZZTdVVHMyZ0ZCNkNlTUdqVgp0bEVCM1dINzl5cnluUmlUQ05yMjdhQWsxeXpmV3AvelVDYnI2cm9oYlF1TXVwUGJJZmxUbUtncUZLUUNlemVtCm9BN2hXUWgyZmZLMXlSMzR6UUZ3eXJna0dkdHN6K0JVNWF2a1RQNGNNbjJUYXNCR2pSVmMvS3FBNUdyYXhaSnkKM0pCdFlrNjBzMUI1U1lLMjYvSEFPdFJLRUNKZDJGcmZPYlB0ZjF0dmo1VkNuck5GbmZHK2FtQ29UR1k2dzJ6VApRdU02WFNtV05SOFlVQVoxK2lZZ2pORm1XQlVMTXhTVmtQaWx3OVd4b2R1Y1puL3I5aWJFeDE3MHR5ZmlSdUtUCnJsOTBBaWZGOU0vWWd3eDBQQXdWMXNXS3o5R1hiUjZQc0FHMXJjcTVlaDFpZlhMU2Y1Y3RIWXZ0cHRPcWlvaTIKQkNZQnlJYzA5UnB5QU1MK1U5QWs3S3NObFQyRUt3dTNZaFJVa3dMTkozY2FzSUxUekNCR2g3bnBEa2UzZ1RaZQpkMWF4NWgrcFcxRGVEeGtvS0pUNUF3Z0dURXJzYndJREFRQUJBb0lDQUFGdjRtMTlwTFFXSW1TVWRYVXkyZ1liCmNkWVdNTlVqc25iekc5MlVIbXZNODNHb2p2cjJISFdwK2hGVlJyaUdMWlpETFJ4MVBqUTZyRUYrMCtZTUJldm8KZUhEVDdLNit3eFNZanExV3RXMWg0cG9KOFVHVnp3M2JrQW5LVklkSVlGeFA3b2dMTkJDQkhJeThvdHZMT3YvQQorM2ljSTFHY2ZBQm1uRXlmWEUrUTJFOGpRNzJYaFhMSExBbnlNMFAvbU9ZVHBRdy92NlhEMWtTMndoZHJsZEYyCm8xZWM0Qkh6VEMxQ1VScEV3cVY2ZjlFd1NNU21nR1BZVzB1a1VndlZBQTZFN3h5bjY3Z2xWSW9xUHhQM2hKeHUKOFRPTFVXVzh6d0Z3Z0NDbTZrbnpGeVN3WkRWVXV2cmVKUlIxOTFVb1BWdU8yU2dhcUYyZHdLazYvV3hmSWxHQgpoRndkbmN1Q1UwdVV5QXp3VUh2bGlEWndWUFFxaVBMbXFYWEp3WjY5RjUzMEZlVHM4L2hUU0Y1UTAwaUFqTmhlClhRbzhJQjA0U1N2VDdMQno1OVg4Y3M0Mkh5VG80YWZ6bWhLK051OEsvQ0ZxOERMT1orRTFtYnhYRE9DM1ZWVHAKaDFFaXd1a0Z0ekpxRzVRSEJjTTlNNVlTK3EzaUw4YXY2N052M29wTm0vUG5YWkdYenFtVjRzK1FwMDdtSUhiVQpsamFCcWVzNGN4RTZZRUtkS1NOSnJ6Y09EVFNFT2hOYUJXN2RNSFRmay8zbXBpODIyNENBdEVJcmVlZy9Ua2VBCjJLWVBmTzJEd3hYZHZJd1NvajBSM0JDbkdVOWVRKzl2L2c5WVU3SXRyS2UxQjlFZTAxNjNUOC9tbnFlZy9QenEKOFNDSFA3Yk1Zb1gxaUlmbjk3MXhBb0lCQVFEZWE2YlY5blQ1dVJHL21FK2FLd0pFTHdkTzFCQTdwc2RIcnV4UApjSW5Hcjdqa3g1S21KV3gvU3c4RXdRZjR1dThEcjYxcC9QUDZLSTZoSzVtQlJhOUpWeVdVbUhTaFFDb0g5TGhPCk5mMkxtMEVOalZVZkdOb2JHMzhsbmhLd082QnNKS3JxTzc2SW5rc3hrN0htaGZ6emlBbFVtTDF5dFhFb0s2Qm4KM3BHZHNRZzEzYjlnWCt6NXZVcGlEOHI5R0U1Rm56cDhNa1BsTWhqcWsvVmp3VXNKcGluSDhMY1B3aEMyZlM5Zwpac2dYdmt6MVR5R2FZVHU5LytBazBMZzJqMU5kNFY0SmIyR0Fvc1NDRUtGQnJrZVNVMTVLK2YrOEtIdFFtMVVBCjBqaExWQWpUTkx1U3d4elB1VUpEaGF4K3kvRFpRRmJPRG1kQmtRWXFBWFpDL0pKNUFvSUJBUURibEFwTGg3c1QKcjhtbjdFcUxEU0ZyVDlQSitsQnhqL210bWd0QVE0MjhBNXVhMFVzbGJ4NGNid0pzcktlejVldkhjWGdmL1Y4cwpBaTFtNnJLcmFBOWlMaFFXSk1wRkFoOEZvRnlIK0pFN1l6N0F3elY2WXRha1h0ZVlrNVIzSlg0UmRZQ0xSeHpDCkpBY25ZMUZDSWRrRzhWcFZPSkZFVnBnWkNFMGRQTldEdHM5cTRyaUR3NXNodWVHd2RldXdoSytwenhQNmlDUmsKNEdER3hzT0hnUERkNy9vVUxzYm9EaEJCT3lOb0VyL2kvWjVQOHpzc1psR20rY2FnTTJETG1oNkxONUlVaTUzWgptNEdHTi81NEN5Zk5pMUFFUitWazlMOTNzOWNkODJuZnlEMkZ3QXNZdkZRcEFRL2c1ekROZ3NsUHZYeUR6OGo1CnNLQmRzcXdnVG53bkFvSUJBQXkxdUIzbjdIMU1ydy8wd3krN0gzRUlBdkhsT2x3K1JvcjVHdlhiSjNSY0hFT3UKaDluSXI2K0NlWVE3QjVxV0RBeDQ0SDc2L25JZ0dTNXFrR1lMdGwySmhsTThkd1d6NWZMNGNBUEFJQkgzT0R0dgpCUnMyejFmWE5XZlA1WjkrZU1kVlBSTVBnTzdMcE41YlkwSWFDLzlhbWJYazJJYVNpYm5TN0dLakhFMFhqYkdPClQxNVJmUGcwY2VpeW9GWGdLckRkelhqRllvM1pWQVVybVUwdkFYdTJyQktKMWR3bnFjN1R6bjVDd1ZKaUJJSE0KR001Nm1mQmNpOUZ1ditnV1BweFJ3WTdtZDNyalVqbGdlK2FGNy84VGxvTFFVR1hQSm1UUHk0YTFmSlFKWkV1MQphcmFUUWJVNUQrbE4zVEtOc3VDblJZNlcwaDIwRE5jZnFFTmhyWGtDZ2dFQVdIN1FxMkkzdnBaeGNwRWo5ZWpECjJFa2k5VnRDQXBMaE1OdE52NGU2WHRVaGFJTURnMEhHWS9WRmgrRUo4ZEl2ZFlGQXhidkxHS1NFQWQrRFJOdTYKbjNvc3RFUDlsVlJtaGxEOEdmelBJNTA3RkZ0WWVVdk9jQTZkVzZ2WEFUSUdIaWs2Tm1maHFrajA3U1gxQU84OQpWYlArRVN5c04xdWpEeXV1VUtOTTlqbStYTGlsWHMxOS8xaTRJZk5VbXg3TzRXUkpEQWJFakRkMktZYkFGU09kCmNBVWd4L09XVEw0bVJQUDlzQnNtWk9pTVhuS01IYmZiSHEyNkpLU3dWVDUzSXVxeG9FQW96U1FFVHNEUWVUY2QKd3BSc0dsMlRrVjJtc1NxMC95ZzBPbkdzZ2ZSRlJLSGFWWEJOSXZwcVM5bHpJd1VlWXMxaWxXZGZLb1F4SlJBYwpyd0tDQVFCemdWeFZxYTV0T0ZudzhRbWZVWU1lN0RIQ1U0cjNSUzFPTndtR29YSTFSTHp6M0k4U1JHSWJOcFYxCnlJczRnRldXd0l1WG40ekxvMCtZZExwT2prRmg1S2FrMEVya2g3QjUvWm01OWZkR013dWpBMnZpUUdZalJyek8Ka1RTQ1hQZ3JHd0s5QmxqWWZlbFM5cVd1aTl2RHVSaEFXUVpPT0NDeVB0eEVjT3ZyOXFmOUtoT2MweEVFTnRVagp6L01CSDc4NnJwckJFQVhuT0FGRkpibWZ0TFhZeTlSaEFhdTJTTURYMGc5dWRIRE1RTk9Cb1dPN2RoLzVBNXZhCkxMa3BWZ3ZvWWtjU1NjRGFKSUtzb2RQTGNManFYWGQ1MVhOV3BDOWNPWkJaUVM4RXVOMVZmR3JqT0RZOW1SOGIKakNvbUgxUDBGenlQVm1MU2JvV21qRGJzMFNGZQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==