Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
- changed-files:
- any-glob-to-any-file: 'spring-prometheus-grafana-example/**/*'

"project: spring-keycloak-example":
- changed-files:
- any-glob-to-any-file: 'spring-keycloak-example/**/*'

"type: dependency-upgrade":
- changed-files:
- any-glob-to-any-file:
- spring-kafka-example/pom.xml
- spring-prometheus-grafana-example/pom.xml
- any-glob-to-any-file: "**/pom.xml"

"ci: github-actions":
- changed-files:
Expand Down
68 changes: 68 additions & 0 deletions .github/workflows/spring-keycloak-example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: spring-keycloak-example CI Build

on:
pull_request:
branches: [master]
paths:
- "spring-keycloak-example/**"
types:
- opened
- synchronize
- reopened

jobs:

integration-tests:
name: Run Unit & Integration Tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: spring-keycloak-example
strategy:
matrix:
distribution: [ 'temurin' ]
java: [ '21' ]
steps:
Comment on lines +21 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Simplify matrix strategy for single values.

Using a matrix strategy with single values adds unnecessary complexity.

Simplify the configuration:

-    strategy:
-      matrix:
-        distribution: [ 'temurin' ]
-        java: [ '21' ]
     steps:
       - uses: actions/checkout@v4
         with:
           fetch-depth: 0
 
-      - name: Set up JDK ${{ matrix.java }}
+      - name: Set up JDK 21
         uses: actions/setup-java@v4.7.1
         with:
-          java-version: ${{ matrix.java }}
-          distribution: ${{ matrix.distribution }}
+          java-version: '21'
+          distribution: 'temurin'
           cache: 'maven'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
strategy:
matrix:
distribution: [ 'temurin' ]
java: [ '21' ]
steps:
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK 21
uses: actions/setup-java@v4.7.1
with:
java-version: '21'
distribution: 'temurin'
cache: 'maven'
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 23-23: too many spaces inside brackets

(brackets)


[error] 23-23: too many spaces inside brackets

(brackets)


[error] 24-24: too many spaces inside brackets

(brackets)


[error] 24-24: too many spaces inside brackets

(brackets)

🤖 Prompt for AI Agents
In .github/workflows/spring-keycloak-example.yml around lines 21 to 25, the
matrix strategy is used with single values for distribution and java, which is
unnecessarily complex. Simplify the workflow by removing the matrix strategy and
directly specifying the distribution and java version in the steps or job
configuration.

- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v4.7.1
with:
java-version: ${{ matrix.java }}
distribution: ${{ matrix.distribution }}
cache: 'maven'
- name: Build and analyze
run: ./mvnw clean verify

health-check:
name: Health Check on Services
runs-on: ubuntu-latest
steps:
- name: Checkout repository and submodules
uses: actions/checkout@v4
with:
submodules: true

- name: Extract service names from docker compose
id: services
run: |
echo "services<<EOF" >> $GITHUB_OUTPUT
docker compose -f ./spring-keycloak-example/compose.yaml config --services >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Start containers with Compose Action
uses: hoverkraft-tech/compose-action@v2.3.0
with:
compose-file: './spring-keycloak-example/compose.yaml'
services: ${{ steps.services.outputs.services }}
up-flags: '--build'
down-flags: '--volumes'

- name: Wait for containers to initialize
run: sleep 10

- name: Check container health
run: |
./.github/scripts/check-container-health.sh "${{ steps.services.outputs.services }}"
Comment on lines +3 to +68
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Fix YAML formatting issues.

The file has formatting inconsistencies that should be addressed.

Apply these formatting fixes:

 on:
   pull_request:
-    branches: [master]
+    branches: ['master']
     paths:
       - "spring-keycloak-example/**"

And add a newline at the end of the file:

       - name: Check container health
         run: |
-          ./.github/scripts/check-container-health.sh "${{ steps.services.outputs.services }}"
+          ./.github/scripts/check-container-health.sh "${{ steps.services.outputs.services }}"
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
pull_request:
branches: [master]
paths:
- "spring-keycloak-example/**"
types:
- opened
- synchronize
- reopened
jobs:
integration-tests:
name: Run Unit & Integration Tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: spring-keycloak-example
strategy:
matrix:
distribution: [ 'temurin' ]
java: [ '21' ]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v4.7.1
with:
java-version: ${{ matrix.java }}
distribution: ${{ matrix.distribution }}
cache: 'maven'
- name: Build and analyze
run: ./mvnw clean verify
health-check:
name: Health Check on Services
runs-on: ubuntu-latest
steps:
- name: Checkout repository and submodules
uses: actions/checkout@v4
with:
submodules: true
- name: Extract service names from docker compose
id: services
run: |
echo "services<<EOF" >> $GITHUB_OUTPUT
docker compose -f ./spring-keycloak-example/compose.yaml config --services >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Start containers with Compose Action
uses: hoverkraft-tech/compose-action@v2.3.0
with:
compose-file: './spring-keycloak-example/compose.yaml'
services: ${{ steps.services.outputs.services }}
up-flags: '--build'
down-flags: '--volumes'
- name: Wait for containers to initialize
run: sleep 10
- name: Check container health
run: |
./.github/scripts/check-container-health.sh "${{ steps.services.outputs.services }}"
on:
pull_request:
branches: ['master']
paths:
- "spring-keycloak-example/**"
types:
- opened
- synchronize
- reopened
jobs:
integration-tests:
name: Run Unit & Integration Tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: spring-keycloak-example
strategy:
matrix:
distribution: [ 'temurin' ]
java: [ '21' ]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v4.7.1
with:
java-version: ${{ matrix.java }}
distribution: ${{ matrix.distribution }}
cache: 'maven'
- name: Build and analyze
run: ./mvnw clean verify
health-check:
name: Health Check on Services
runs-on: ubuntu-latest
steps:
- name: Checkout repository and submodules
uses: actions/checkout@v4
with:
submodules: true
- name: Extract service names from docker compose
id: services
run: |
echo "services<<EOF" >> $GITHUB_OUTPUT
docker compose -f ./spring-keycloak-example/compose.yaml config --services >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Start containers with Compose Action
uses: hoverkraft-tech/compose-action@v2.3.0
with:
compose-file: './spring-keycloak-example/compose.yaml'
services: ${{ steps.services.outputs.services }}
up-flags: '--build'
down-flags: '--volumes'
- name: Wait for containers to initialize
run: sleep 10
- name: Check container health
run: |
./.github/scripts/check-container-health.sh "${{ steps.services.outputs.services }}"
🧰 Tools
🪛 YAMLlint (1.37.1)

[warning] 3-3: truthy value should be one of [false, true]

(truthy)


[error] 23-23: too many spaces inside brackets

(brackets)


[error] 23-23: too many spaces inside brackets

(brackets)


[error] 24-24: too many spaces inside brackets

(brackets)


[error] 24-24: too many spaces inside brackets

(brackets)


[error] 68-68: no new line character at the end of file

(new-line-at-end-of-file)

🤖 Prompt for AI Agents
In .github/workflows/spring-keycloak-example.yml from lines 3 to 68, fix YAML
formatting inconsistencies by ensuring proper indentation and spacing throughout
the file, especially under keys like 'on', 'jobs', and each job's steps. Also,
add a newline at the end of the file to comply with standard file formatting
conventions.

1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<modules>
<module>spring-kafka-example</module>
<module>spring-prometheus-grafana-example</module>
<module>spring-keycloak-example</module>
</modules>

</project>
62 changes: 62 additions & 0 deletions spring-keycloak-example/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Include any files or directories that you don't want to be copied to your
# container here (e.g., local build artifacts, temporary files, etc.).
#
# For more help, visit the .dockerignore file reference guide at
# https://docs.docker.com/go/build-context-dockerignore/

**/.DS_Store
**/.classpath
**/.dockerignore
**/.env
**/.factorypath
**/.git
**/.gitignore
**/.idea
**/.project
**/.sts4-cache
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/.next
**/.cache
**/*.dbmdl
**/*.jfm
**/charts
**/docker-compose*
**/compose.y*ml
**/Dockerfile*
**/secrets.dev.yaml
**/values.dev.yaml
**/vendor
LICENSE
README.md
**/*.class
**/*.iml
**/*.ipr
**/*.iws
**/*.log
**/.apt_generated
**/.gradle
**/.gradletasknamecache
**/.nb-gradle
**/.springBeans
**/build
**/dist
**/gradle-app.setting
**/nbbuild
**/nbdist
**/nbproject/private
**/target
*.ctxt
.mtj.tmp
.mvn/timing.properties
buildNumber.properties
dependency-reduced-pom.xml
hs_err_pid*
pom.xml.next
pom.xml.releaseBackup
pom.xml.tag
pom.xml.versionsBackup
release.properties
replay_pid*
2 changes: 2 additions & 0 deletions spring-keycloak-example/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf
32 changes: 32 additions & 0 deletions spring-keycloak-example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/
19 changes: 19 additions & 0 deletions spring-keycloak-example/.mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
Comment on lines +17 to +19
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add SHA-256 checksum for Maven distribution

Including distributionSha256Sum guards against supply-chain attacks and corrupted downloads.

 distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
+distributionSha256Sum=<insert-official-sha256>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
distributionSha256Sum=<insert-official-sha256>
🤖 Prompt for AI Agents
In spring-keycloak-example/.mvn/wrapper/maven-wrapper.properties around lines 17
to 19, add a new property named distributionSha256Sum with the SHA-256 checksum
of the Maven distribution zip file specified in distributionUrl. This ensures
the integrity and authenticity of the downloaded Maven distribution by verifying
its checksum during the wrapper execution.

47 changes: 47 additions & 0 deletions spring-keycloak-example/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
FROM eclipse-temurin:21-jdk-jammy as deps

WORKDIR /build

COPY --chmod=0755 mvnw mvnw
COPY .mvn/ .mvn/

RUN --mount=type=bind,source=pom.xml,target=pom.xml \
--mount=type=cache,target=/root/.m2 ./mvnw dependency:go-offline -DskipTests

FROM deps as package

WORKDIR /build

COPY ./src src/
RUN --mount=type=bind,source=pom.xml,target=pom.xml \
--mount=type=cache,target=/root/.m2 \
./mvnw package -DskipTests && \
mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar

FROM package as extract

WORKDIR /build

RUN java -Djarmode=layertools -jar target/app.jar extract --destination target/extracted

FROM eclipse-temurin:21-jre-jammy AS final

ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
USER appuser

COPY --from=extract build/target/extracted/dependencies/ ./
COPY --from=extract build/target/extracted/spring-boot-loader/ ./
COPY --from=extract build/target/extracted/snapshot-dependencies/ ./
COPY --from=extract build/target/extracted/application/ ./
Comment on lines +40 to +43
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add WORKDIR before COPY operations.

The COPY operations use relative destinations without a WORKDIR set, which defaults to the root directory.

Add a WORKDIR directive after the USER declaration:

 USER appuser
+
+WORKDIR /app
 
 COPY --from=extract build/target/extracted/dependencies/ ./
 COPY --from=extract build/target/extracted/spring-boot-loader/ ./
🧰 Tools
🪛 Hadolint (2.12.0)

[warning] 40-40: COPY to a relative destination without WORKDIR set.

(DL3045)


[warning] 41-41: COPY to a relative destination without WORKDIR set.

(DL3045)


[warning] 42-42: COPY to a relative destination without WORKDIR set.

(DL3045)


[warning] 43-43: COPY to a relative destination without WORKDIR set.

(DL3045)

🤖 Prompt for AI Agents
In spring-keycloak-example/Dockerfile around lines 40 to 43, the COPY commands
use relative paths without a preceding WORKDIR, causing files to be copied to
the root directory by default. Add a WORKDIR directive immediately after the
USER declaration to set the working directory for these COPY operations,
ensuring files are copied to the intended location.


EXPOSE 80
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Port 80 requires elevated privileges.

Exposing port 80 conflicts with running as a non-root user. Non-root users cannot bind to privileged ports (< 1024).

Use a non-privileged port:

-EXPOSE 80
+EXPOSE 8080

Ensure your application is configured to listen on the same port.

🤖 Prompt for AI Agents
In spring-keycloak-example/Dockerfile at line 45, the Dockerfile exposes port
80, which requires elevated privileges and conflicts with running the container
as a non-root user. Change the exposed port to a non-privileged port number
above 1024, such as 8080, and update the application configuration to listen on
this new port to maintain consistency.


ENTRYPOINT [ "java", "org.springframework.boot.loader.launch.JarLauncher" ]
10 changes: 10 additions & 0 deletions spring-keycloak-example/Dockerfile.keycloak
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM quay.io/keycloak/keycloak:26.3 AS builder

WORKDIR /opt/keycloak
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:26.3

COPY --from=builder /opt/keycloak/ /opt/keycloak/

ENTRYPOINT ["/opt/keycloak/bin/kc.sh", "start"]
Comment on lines +1 to +10
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add a HEALTHCHECK and drop root user
Consider adding an explicit HEALTHCHECK and switching to a non-root user to reduce CVE blast-radius and satisfy basic container hardening scanners.
Example diff:

@@
 COPY --from=builder /opt/keycloak/ /opt/keycloak/
 
+# HEALTHCHECK to surface liveness to orchestrators
+HEALTHCHECK --interval=30s --timeout=5s --start-period=30s CMD curl -f http://localhost:8080/health/live || exit 1
+
+# Security: run as an unprivileged user
+USER 1000
+
 ENTRYPOINT ["/opt/keycloak/bin/kc.sh", "start"]
🧰 Tools
🪛 Checkov (3.2.334)

[LOW] 1-10: Ensure that HEALTHCHECK instructions have been added to container images

(CKV_DOCKER_2)


[LOW] 1-10: Ensure that a user for the container has been created

(CKV_DOCKER_3)

🤖 Prompt for AI Agents
In spring-keycloak-example/Dockerfile.keycloak around lines 1 to 10, the
Dockerfile lacks a HEALTHCHECK instruction and runs as root, which poses
security risks. Add a HEALTHCHECK instruction that periodically verifies the
Keycloak service health, for example by checking the server's HTTP status. Also,
create and switch to a non-root user before running the ENTRYPOINT to reduce
security vulnerabilities and comply with container hardening best practices.

36 changes: 36 additions & 0 deletions spring-keycloak-example/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

services:
Comment on lines +1 to +2
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove leading blank line
Starts with an empty line, tripping YAML-lint (empty-lines).

- 
 services:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
services:
services:
🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 1-1: too many blank lines (1 > 0)

(empty-lines)

🤖 Prompt for AI Agents
In spring-keycloak-example/compose.yaml at the beginning of the file (lines
1-2), remove the leading blank line before the "services:" key to comply with
YAML linting rules and avoid empty line errors.


app:
container_name: app
build:
context: .
dockerfile: Dockerfile
environment:
SERVER_PORT: 80
SPRING_PROFILES_ACTIVE: "default"
ports:
- "80:80"
depends_on:
- keycloak

keycloak:
container_name: keycloak
build:
context: .
dockerfile: Dockerfile.keycloak
ports:
- "8080:8080"
environment:
KC_DB: dev-file
KC_HTTP_ENABLED: "true"
KC_HTTP_PORT: "8080"
KC_HOSTNAME: localhost
KC_HEALTH_ENABLED: "true"
KC_METRICS_ENABLED: "true"
KEYCLOAK_ADMIN: admin #⚠️ DO NOT USE IN PRODUCTION
KEYCLOAK_ADMIN_PASSWORD: admin #⚠️ DO NOT USE IN PRODUCTION
KC_HTTPS_CERTIFICATE_FILE: /opt/keycloak/certs/tls.crt
KC_HTTPS_CERTIFICATE_KEY_FILE: /opt/keycloak/certs/tls.key
volumes:
- ./docker/keycloak:/opt/keycloak/certs
7 changes: 7 additions & 0 deletions spring-keycloak-example/docker/keycloak/cert-info.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
TLS Certificates for Keycloak
These certificates were manually generated using the following command:

```bash
openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt -days 365 -nodes \
-subj "/CN=localhost"
```
29 changes: 29 additions & 0 deletions spring-keycloak-example/docker/keycloak/tls.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFCTCCAvGgAwIBAgIUIyugoLVFZznlfIT1+VwNY7TKaH0wDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDgwMjAwNDYzM1oXDTI2MDgw
MjAwNDYzM1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEA59ml/0oqbcJ1JnLoPCKtkma7mSow0hFLZDE26N52R+4K
Xw3trgNW2JL2Z3xQTMnRwHdMwKduTjQQob69bP0K7x4F6nNsrix4u88pOio8r+D6
cJX3eRnfDqDclGCUy76qqpe5WUnQBsOKVfV2dvAKLb1aNttw8E2hM0/RGW1m9mKH
KJlvjS/4qTH8tmm5AI7eEJZfHYsONAzw/xsKhFkPwX2FkGn+/efqmJ7ufHMsD5tD
zN9fjvt9iYhhWKuJA2pFwol+NDz+25w8ksyxnH8HKREqSkpg3l2owuwrBRG+F3vh
IAFxJaC0CGvUY3suqIAUCYcaPxecxjWS08ySZuojh27s3/9dufDx1CSXCX1+iS+U
lYOEI7SaLq6KIbo8BfrkqDNrUI6wJxLOYrokv1s2XSg4gEeCXh8VcjK2rbUs8QAI
6lakr1hAuvCq6PqEsRcioMzUBLeb3r0klfr3sGW3S/PtidvvtBRDnQ07pysvntGq
FQXd9BFS0+36B2SmbZPdx6nvS1EXwXwHCxzhsMMcRgP9W9rZekLfAhqKVqrRfLWN
r4Oq9TCeYGrcUB8unvKP2irVMoKnUD+PyUErzg/ZLLCnjEleNp83QuAYPTTpe0xE
Os+KCkuw4Mb5s4BbWGm7jeOAvGrjLLMzdaDRYaMp4mCL5wfbGTVxodk9LqP4D8cC
AwEAAaNTMFEwHQYDVR0OBBYEFO/90I29W64gE7TsZLYRQm/AafCoMB8GA1UdIwQY
MBaAFO/90I29W64gE7TsZLYRQm/AafCoMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
hvcNAQELBQADggIBAL9SLQ+Get1P7WMv4EAaxaktKgAvNpoSu8C57Cp0Gm07wkYP
wx+iQ65NsZZgqXDkzHdsV1Qp4ETNFrd/zhgYx0LEVCVDkHGcxFeadDm5biSm942b
7l4hBXQbDP83FyedVyUimRsyC1xacBZUmFN6E2w1H+fDsWSFP4PbawXo6AldWZkh
pM5CC36cyXeTUb2qhLnX0qJy29O2ixmNlSGDR0cH6cyK0Qorh7NiS3c4M5l7FRTC
dwcQxKY1pTQ8KLTTeDNBqXwegl2UbH4SPMIBUnpYUcRaHiFOGKa0CZLe4nr/Jjaj
rNcRq7ddeastfYEzBn9oympmkTuKkNYBjiGYYPBYFy9XpxjqCxC++YmR1rzdt91w
RJ3pPopRm0RHx4lX9o9sqNn9xYb0wCJRq4A5Tez7Q0lUY8uAQGQdLFnikIS/GSAT
avSR4O3pgyj9Ua0BxXKOkXmLDpMurF5a9LB1eyoFV8H80Uj4lqmrYpgA6BUyy6By
G85ca6K9UZczGUHFtttqMZrSqOqBJxkipfktlcqNBqUqNvgk1JjsWysjL2fcQ7Xq
fXIdSd5OWf2Gq6pPFCWo4Qff7Bx8kfTNsaYcEuA0dsJysjYv9uQ3T4FmRSJuDNAZ
ceq3T5dzNHSP0cp9fb7WxZCfMsQuZUyYJy/O6g3xIrykPS076Mgn+KLVoKJ9
-----END CERTIFICATE-----
Loading