diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 3e8af34..d2c9b20 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -2,9 +2,9 @@ name: Pylint and Pytest on: push: - branches: [ "main" ] + branches: [ "main", "mtls-staging" ] pull_request: - branches: [ "main" ] + branches: [ "main", "mtls-staging" ] permissions: contents: read diff --git a/README.md b/README.md index 53ab215..45a66ee 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Hello World Python App +# Python Hello World App ## Disclaimer @@ -7,820 +7,8 @@ > **already have full access** to the EIAP Ecosystem. > If you do not have this access, **please do not proceed.** +Python Hello World App Documentation [Here](https://developer.intelligentautomationplatform.ericsson.net/#tutorials/sample-app-in-python). + **Note:** If you need help accessing the EIAP Ecosystem, contact support at this **email address:** - -## Introduction - -This is a simple Hello World Python App with the following three endpoints: - -- **/sample-app/python/hello** is a sample endpoint. - -- **/sample-app/python/health** is an endpoint for an external agent to - monitor the App liveliness. - -- **/sample-app/python/metrics** is an endpoint that presents - the number of successful and failed invocations of - the '/sample-app/python/hello' endpoint. - -**Note:** X.509 certificates are used for authentication, and - mTLS uses them to secure communication between the App and the platform. - -## Build Docker - -Extract the downloaded sample App package. Using a command line tool, - go inside the extracted `eric-oss-hello-world-python-app-` directory. - -```bash -cd /eric-oss-hello-world-python-app- -``` - -Rename the `Dockerfile-template` file to `Dockerfile`. - -```bash -mv Dockerfile-template Dockerfile -``` - -Replace `` in the Dockerfile with a slim Python base image. -Refer to: [Python on Dockerâ„¢ Hub](https://hub.docker.com/_/python) - -Run the following command to build the image. - -```bash -APP_VERSION= \ -APP_IMAGE=proj-eric-oss-drop/eric-oss-hello-world-python-app: \ -ENVOY_IMAGE=proj-eric-oss-drop/eric-oss-hello-world-python-app-envoy: \ -docker compose build --no-cache -``` - -## Run Docker Image - -A port binding on port 8050 is done to expose the endpoints. - -```bash -docker run -p 8050:8050 --rm --name python-sample-app proj-eric-oss-drop/eric-oss-hello-world-python-app: -docker run -d --name envoy --link python-sample-app -p 8080:8080 -p 8443:8443 proj-eric-oss-drop/eric-oss-hello-world-python-app-envoy: -``` - -Run a curl request to the /sample-app/python/hello endpoint of the app. -The request should return a "Hello World!!" response. - -```bash -curl -is localhost:8050/sample-app/python/hello -``` - -Example Output: - -```http -HTTP/1.1 200 OK -Date: Thu, 17 Jun 2021 14:46:46 GMT -Content-Length: 13 -Content-Type: text/plain; charset=utf-8 - -Hello World!! -``` - -## Build the CSAR package - -For this step, install the [App Package Tool](https://developer.intelligentautomationplatform.ericsson.net/#capabilities/app-administration/tutorial-package-app). - -Once installed, the tool will be available as a Docker image -named `armdocker.rnd.ericsson.se/proj-eric-oss-dev-test/releases/eric-oss-app-package-tool:latest` - -**Note:** In the commands below, make sure to replace `` -with the correct Python Sample App version. Run the following commands -from within your project directory -`eric-oss-hello-world-python-app-`. - -```bash -mkdir -p helloworldAppPackage -``` - -The zip file includes a `csar` directory, which has the structure of the -CSAR package. - -```bash -cp -r ./csar/* ./helloworldAppPackage/ -``` - -Run the following command to generate an archive of the chart. - -```bash -helm package ./charts/eric-oss-hello-world-python-app/ -``` - -Move the created .tgz file to the OtherDefinitions/ASD directory. - -```bash -mv eric-oss-hello-world-python-app-.tgz ./helloworldAppPackage/OtherDefinitions/ASD/ -``` - -Create a folder where the CSAR App package will be stored into. - -```bash -mkdir csar-output -``` - -Generate an archive of the Docker image and store it temporarily in the `csar-output` -directory. - -```bash -docker save \ - proj-eric-oss-drop/eric-oss-hello-world-python-app: \ - proj-eric-oss-drop/eric-oss-hello-world-python-app-envoy: \ - -o ./csar-output/docker.tar -``` - -Run the following command locally to create a CSAR App package using the -eric-oss-app-package-tool. - -```bash -docker run --init --rm \ - --volume $PWD/csar-output/:/tmp/csar/ \ - --volume $HOME/.docker:/root/.docker \ - --volume /var/run/docker.sock:/var/run/docker.sock \ - --workdir /target \ - --volume $PWD/helloworldAppPackage:/target \ - armdocker.rnd.ericsson.se/proj-eric-oss-dev-test/releases/eric-oss-app-package-tool:latest \ - generate --tosca /target/Metadata/Tosca.meta \ - --name helloworldAppPackage \ - --images /tmp/csar/docker.tar \ - --helm3 \ - --output /tmp/csar -``` - -Run the following command to verify if the CSAR Package was created successfully. - -```bash -ls ./csar-output -``` - -`helloworldAppPackage.csar` is visible in the directory. - -## Onboard the App - -### Prerequisites for Onboarding - -Contact the platform administrator to request the following: - -- A Client certificate, Client key and platform CA certificate, - needed for secure communication with the platform APIs. -- Client ID to access the platform with the required roles, needed for authorized -communication with the platform APIs used to *onboard and instantiate* the -Hello World App. Include the required roles listed below in the request. - -| Role | Role Description | -| --------------------------------------------------------------- | ----------------------------------------------------------------------------- | -| AppMgr_Application_Administrator | Administrator access to App Administration onboarding and instantiating Apps. | -| AppMgr_Application_Operator | Operator access to App Administration onboarding and instantiating Apps. | -| Exposure_Application_Administrator | Access to Service Exposure Onboarding APIs for the Apps. | -| UserAdministration_ExtAppRbac_Application_SecurityAdministrator | Access to Service Exposure Access control APIs for the Apps. | - -See [Client Access to REST APIs](https://developer.intelligentautomationplatform.ericsson.net/#tutorials/client-access) - for further details on client authentication. - -**Note:** Replace `` with the valid `R1 host` provided by platform administrator. - -Use the following command to generate a valid access token: - -```bash -curl --cert --key --cacert --request POST \ -https:///auth/realms/master/protocol/openid-connect/token \ ---header 'content-type: application/x-www-form-urlencoded' \ ---data "grant_type=client_credentials&client_id=" -``` - -This command returns an access token, which is used in the commands in the -following steps. See the following example of a response containing the -access token: - -```bash - "access_token": "eyJhbGciOiJSUze168rQBwD4....", - "expires_in": 300, - "refresh_expires_in": 0, - "token_type": "Bearer", - "not-before-policy": 0, - "scope": "profile" -``` - -### Steps for Onboarding - -Onboard the **Hello World CSAR App Package** using [App Administration](https://developer.intelligentautomationplatform.ericsson.net/#capabilities/app-administration/developer-guide-manage?chapter=onboard). - -Run the following command. - -```bash -curl --cert --key --cacert --location --request POST 'https:///app-onboarding/v2/app-packages' \ ---header 'Authorization: Bearer ' \ ---header 'accept: application/json' \ ---form 'file=@"/helloworldAppPackage.csar"' -``` - -Example of command result: - -```json -{ - "fileName": "helloworldAppPackage.csar", - "onboardingJob": { - "id": "af036040-a732-4af9-b65a-8103da56c35c", - "href": "/onboarding-jobs/af036040-a732-4af9-b65a-8103da56c35c" - } -} -``` - -An onboarding-job `id` is shown in the command result -(af036040-a732-4af9-b65a-8103da56c35c in the example). -This is the `JOB_ID`. Use the `JOB_ID` to get the -status of the onboarding process in the following commands: - -```bash -curl --cert --key --cacert --location --request GET 'https:///app-onboarding/v2/onboarding-jobs/' \ ---header 'Authorization: Bearer ' \ ---header 'accept: application/json' -``` - -It can take several minutes for the status to change to `ONBOARDED`. -Repeat the command until the status is changed to `ONBOARDED`. - -Example of command result: - -```json -{ - "id": "af036040-a732-4af9-b65a-8103da56c35c", - "fileName": "helloworldAppPackage.csar", - "packageVersion": "4.0.0-0", - "packageSize": "51.7659MiB", - "vendor": "Ericsson", - "type": "rApp", - "onboardStartedAt": "2025-05-31T13:51:56.616Z", - "status": "ONBOARDED", - "onboardEndedAt": "2025-05-31T13:51:59.955Z", - "events": [ - { - "type": "INFO", - "title": "Stored 1 out of 4 artifacts", - "detail": "Uploaded eric-oss-hello-world-python-appASD.yaml", - "occurredAt": "2025-05-31T13:51:58.042Z" - }, - { - "type": "INFO", - "title": "Stored 2 out of 4 artifacts", - "detail": "Uploaded eric-oss-hello-world-python-app", - "occurredAt": "2025-05-31T13:51:58.043Z" - }, - { - "type": "INFO", - "title": "Stored 3 out of 4 artifacts", - "detail": "Uploaded docker.tar", - "occurredAt": "2025-05-31T13:51:59.792Z" - }, - { - "type": "INFO", - "title": "Stored 4 out of 4 artifacts", - "detail": "Uploaded security-metadata.json", - "occurredAt": "2025-05-31T13:51:59.812Z" - } - ], - "self": { - "href": "/onboarding-jobs/af036040-a732-4af9-b65a-8103da56c35c" - }, - "app": { - "id": "rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0", - "href": "app-lifecycle-management/v3/apps/rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0" - } -} -``` - -The `APP_ID` is the `id` of the `app` returned in the previous -command (rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0 in the example). -Run the following command to initialize the App. - -```bash -curl --cert --key --cacert --location --request POST 'https:///app-lifecycle-management/v3/apps//initialization-actions' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' \ --d '{"action": "INITIALIZE"}' -``` - -Example of command result: - -```json -{ - "app": { - "status": "INITIALIZING", - "id": "rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0", - "href": "/apps/rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0" - } -} -``` - -Repeat the following command until the status is changed to `INITIALIZED`. - -```shell -curl --cert --key --cacert --location --request GET 'https:///app-lifecycle-management/v3/apps/' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' -``` - -Example of command result: - -```json -{ - "id": "rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0", - "type": "rApp", - "provider": "Ericsson", - "name": "eric-oss-hello-world-python-app", - "version": "4.0.0-0", - "mode": "DISABLED", - "status": "INITIALIZED", - "createdAt": "2025-05-31T13:51:59.931Z", - "components": [ - { - "type": "ASD", - "name": "eric-oss-hello-world-python-app", - "version": "4.0.0-0", - "artifacts": [ - { - "name": "docker.tar", - "type": "IMAGE" - }, - { - "name": "eric-oss-hello-world-python-appASD.yaml", - "type": "OPAQUE" - }, - { - "name": "eric-oss-hello-world-python-app", - "type": "HELM" - } - ] - }, - { - "type": "SECURITYMANAGEMENT", - "name": "security-mgmt", - "version": "1.0.0", - "artifacts": [ - { - "name": "security-metadata.json", - "type": "OPAQUE" - } - ] - } - ], - "permissions": [ - { - "resource": "kafka", - "scope": "GLOBAL" - } - ], - "roles": [], - "events": [ - { - "type": "INITIALIZE", - "title": "SUCCEEDED", - "detail": "INITIALIZE has successfully completed", - "createdAt": "2025-05-31T13:55:50.421Z" - }, - { - "type": "INITIALIZE", - "title": "STARTED", - "detail": "INITIALIZE has started", - "createdAt": "2025-05-31T13:55:34.171Z" - }, - { - "type": "CREATE", - "title": "SUCCEEDED", - "detail": "CREATE has successfully completed", - "createdAt": "2025-05-31T13:51:59.945Z" - } - ], - "self": { - "href": "/apps/rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0" - } -} -``` - -Run the following command to switch the App mode from 'DISABLED' to 'ENABLED'. - -```bash -curl --cert --key --cacert --location --request PUT 'https:///app-lifecycle-management/v3/apps//mode' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' \ --d '{"mode": "ENABLED"}' -``` - -Example of command result: - -```json -{ - "mode": "ENABLED", - "app": { - "id": "rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0", - "href": "/apps/rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0" - } -} -``` - -## Instantiate the App - -This section describes how the App can communicate with IAM and produce logs to - the platform. The App is instantiated using App Administration and the API is - exposed and secured by the Service Exposure capability. - -### Prerequisites for Instantiation - -- You need the access token generated in **Onboard the App** prerequisite to - access the App Manager for instantiating the Hello World CSAR App Package. -- Contact your platform administrator to generate the required App key, - certificates key, certificates, and the secrets which store them. The - details of the secrets, keys, certs and EIC endpoint details will be passed - to App Administration through the `userDefinedHelmParameters` when - instantiating the App. Refer to - [App Certificate Provisioning Developer Guide](https://developer.intelligentautomationplatform.ericsson.net/#capabilities/app-cert-provisioning/developer-guide) - to understand how certificates are loaded into the App during - instantiation for secure communication. The required parameters are: - - - The `iamBaseUrl` must point to the `R1 host`, as the `/sample-app/python/hello` - endpoint in this sample app first communicates with IAM to obtain a - client token (login) before returning the "Hello World!!" string response. - - The`appSecretName`, `appKeyFileName`, `appCertFileName`, - `platformCaCertSecretName` and `platformCaCertFileName` to enable - secure communication between the App and the platform. - - The `logEndpoint` which facilitates streaming App logs to platform, - supports only mTLS communication. For more information on the variable - values required, see [App Logging Developer Guide to Produce logs](https://developer.intelligentautomationplatform.ericsson.net/#capabilities/app-logging/how-to-produce-logs?chapter=identify-environment-and-secret-variables-names). - -### Steps for Instantiation - -Use the App Administration capability to instantiate the - **Hello World CSAR App**. For more details on instantiating an App, see - [App Administration](https://developer.intelligentautomationplatform.ericsson.net/#capabilities/app-administration/developer-guide-manage?chapter=instantiate). -Run the following commands to start the instantiation process using the - `APP_ID` from **Onboard the App**. - -#### Create App Instance - -```shell -curl --cert --key --cacert --location --request POST 'https:///app-lifecycle-management/v3/app-instances' \ ---header 'accept: application/json' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' \ --d '{ - "appId": "" -}' -``` - -Example command result: - -```json -{ - "id": "rapp-ericsson-eric-oss-hello-world-python-app-68129972", - "appId": "rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0", - "status": "UNDEPLOYED", - "credentials": { - "clientId": "rapp-ericsson-eric-oss-hello-world-python-app-68129972" - }, - "componentInstances": [ - { - "name": "eric-oss-hello-world-python-app", - "version": "4.0.0-0", - "type": "ASD", - "deployState": "UNDEPLOYED", - "properties": { - "userDefinedHelmParameters": {}, - "namespace": "", - "timeout": 5 - } - }, - { - "name": "security-mgmt", - "version": "1.0.0", - "type": "SECURITYMANAGEMENT", - "properties": { - "authenticatorType": "client-x509" - } - } - ], - "self": { - "href": "/app-instances/rapp-ericsson-eric-oss-hello-world-python-app-68129972" - }, - "app": { - "href": "/apps/rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0" - } -} -``` - -An app-instance `id` is shown in the command result - (rapp-ericsson-eric-oss-hello-world-python-app-68129972 in the example). This - is the `APP_INSTANCE_ID` used in the following commands. - -#### Deploy App Instance - -> All `userDefinedHelmParameters` are required for successful instantiation - of your App. - -```shell -curl --cert --key --cacert --location --request POST 'https:///app-lifecycle-management/v3/app-instances//deployment-actions' \ - --header 'accept: application/json' \ - --header 'Content-Type: application/json' \ - --header 'Authorization: Bearer ' \ - -d '{ - "type": "DEPLOY", - "additionalData": { - "componentInstances": [ - { - "name": "eric-oss-hello-world-python-app", - "properties": { - "timeout": 5, - "userDefinedHelmParameters": { - "iamBaseUrl": "https://", - "logEndpoint": "", - "platformCaCertSecretName": "", - "appSecretName": "", - "platformCaCertFileName": "", - "appKeyFileName": "", - "appCertFileName": "", - } - } - } - ] - } -}' -``` - -See the following example command result: - -```json -{ - "type": "DEPLOY", - "additionalData": { - "componentInstances": [ - { - "name": "eric-oss-hello-world-python-app", - "properties": { - "timeout": 5, - "userDefinedHelmParameters": { - "platformCaCertSecretName": "", - "platformCaCertFileName": "", - "iamBaseUrl": "https://", - "appSecretName": "", - "logEndpoint": "", - "appKeyFileName": "", - "appCertFileName": "", - } - } - } - ] - }, - "appInstance": { - "status": "DEPLOYING", - "href": "/app-instances/rapp-ericsson-eric-oss-hello-world-python-app-68129972" - } -} -``` - -Use the App instance ID in the following command to check the instantiation - status. Repeat the command until the health status is changed - to `"status":"DEPLOYED"`. - -```shell -curl --cert --key --cacert --location --request GET 'https:///app-lifecycle-management/v3/app-instances/' \ ---header 'accept: application/json' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' -``` - -```json -{ - "id": "rapp-ericsson-eric-oss-hello-world-python-app-68129972", - "appId": "rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0", - "status": "DEPLOYED", - "createdAt": "2025-05-31T14:01:01.741Z", - "updatedAt": "2025-05-31T14:04:16.300Z", - "credentials": { - "clientId": "rapp-ericsson-eric-oss-hello-world-python-app-68129972" - }, - "componentInstances": [ - { - "name": "eric-oss-hello-world-python-app", - "version": "4.0.0-0", - "type": "ASD", - "deployState": "DEPLOYED", - "properties": { - "userDefinedHelmParameters": { - "iamBaseUrl": "https://", - "logEndpoint": "", - "platformCaCertSecretName": "", - "appSecretName": "", - "platformCaCertFileName": "", - "appKeyFileName": "", - "appCertFileName": "", - }, - "namespace": "", - "timeout": 5 - } - }, - { - "name": "security-mgmt", - "version": "1.0.0", - "type": "SECURITYMANAGEMENT", - "properties": { - "authenticatorType": "client-x509" - } - } - ], - "events": [ - { - "type": "DEPLOY", - "title": "SUCCEEDED", - "detail": "DEPLOY has successfully completed", - "createdAt": "2025-05-31T14:04:16.297Z" - }, - { - "type": "DEPLOY", - "title": "STARTED", - "detail": "DEPLOY has started", - "createdAt": "2025-05-31T14:04:15.609Z" - }, - { - "type": "CREATE", - "title": "SUCCEEDED", - "detail": "CREATE has successfully completed", - "createdAt": "2025-05-31T14:01:01.753Z" - } - ], - "self": { - "href": "/app-instances/rapp-ericsson-eric-oss-hello-world-python-app-68129972" - }, - "app": { - "href": "/apps/rapp-ericsson-eric-oss-hello-world-python-app-4-0-0-0" - } -} -``` - -To view your logs, access EIC and open your log viewer. -Within the log viewer, you can filter for App Logging and view the results. - -#### Onboard the Hello World Python App APIs - -Use Service Exposure to expose the Hello World App API. -For details, see [Service Exposure - Developer Guide](https://developer.intelligentautomationplatform.ericsson.net/#capabilities/service-exposure/api-exposure-developer-guide). - -To create an API to be onboarded, run the following commands: - -```bash -curl --cert --key --cacert --location --request POST 'https:///hub/apiprovisioning/v1/admin/v3/apis' \ ---header 'Authorization: Bearer ' \ ---header 'Content-Type: application/json' \ ---data '{ - "serviceCapabilityId": "hello-world-python-route-001", - "status": "active", - "apiPrefix": "/app/ericsson-helloWorldPythonApp", - "apiName": "hello-world-python-route", - "apiVersion": "v1", - "apiCategory": "/APIGM/category/api", - "apiDefinition": [ - { - "operationName": "/sample-app/python/hello/GET", - "urlPattern": "/sample-app/python/hello", - "methods": [ - "GET" - ] - } - ] -}' -``` - -To create an endpoint for the previously generated API, run the -following command: - -```bash -curl --cert --key --cacert --location --request POST 'https:///hub/apiprovisioning/v1/admin/v3/apis/hello-world-python-route-001/endpoints' \ ---header 'Authorization: Bearer ' \ ---header 'Content-Type: application/json' \ ---data '{ - "endpointId": "python-hello-001", - "serverUrl": "http://eric-oss-hello-world-python-app:8050" -}' -``` - -To bind the plugin for authorization of the previously -generated API, run the following command: - -```bash -curl --cert --key --cacert --location --request PUT 'https:///hub/apiprovisioning/v1/admin/v3/apis/hello-world-python-route-001/phases/auth/plugin-list' \ ---header 'Authorization: Bearer ' \ ---header 'Content-Type: application/json' \ ---data '[ - { - "name": "requestPartyTokenInterceptor" - } -]' -``` - -To configure the binded plugin for authorization, -run the following command: - -```bash -curl --cert --key --cacert --location --request PUT 'https:///hub/apiprovisioning/v1/admin/v3/apis/hello-world-python-route-001/plugins/requestPartyTokenInterceptor/configuration' \ ---header 'Authorization: Bearer ' \ ---header 'Content-Type: application/json' \ ---data '{ - "configurationSchemaVersion": "v0", - "configuration": { - "defaultResourceServer": "eo" - } -}' -``` - -#### Manage access control for the Hello World Python App APIs - -To allow access to the API endpoints provided by the 'Hello World' App, -Role-Based Access Control (RBAC) configuration is required. To add the -RBAC policy run the following curl command: - -```bash -curl --cert --key --cacert --location --request POST 'https:///idm/rolemgmt/v1/extapp/rbac' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' \ ---data '{ - "tenant": "master", - "roles": [ - { - "name": "Python_SampleApp_Application_Administrator" - } - ], - "authorization": { - "resources": [ - { - "name": "python_sample_app_hello", - "type": "urn:eo:resources:extrapp", - "ownerManagedAccess": false, - "uris": [ - "/app/ericsson-helloWorldPythonApp/hello-world-python-route/v1/sample-app/python/hello" - ], - "scopes": [ - { - "name": "PATCH" - }, - { - "name": "DELETE" - }, - { - "name": "GET" - }, - { - "name": "POST" - }, - { - "name": "PUT" - } - ] - } - ], - "policies": [ - { - "name": "Python Sample App Hello Policy", - "type": "role", - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "config": { - "roles": "[{\"id\":\"Python_SampleApp_Application_Administrator\",\"required\":false}]" - } - }, - { - "name": "Python Sample App Hello Permission", - "type": "scope", - "logic": "POSITIVE", - "decisionStrategy": "AFFIRMATIVE", - "config": { - "resources": "[\"python_sample_app_hello\"]", - "scopes": "[\"GET\",\"PUT\",\"POST\",\"DELETE\",\"PATCH\"]", - "applyPolicies": "[\"Python Sample App Hello Policy\"]" - } - } - ], - "scopes": [ - { - "name": "GET" - }, - { - "name": "POST" - }, - { - "name": "DELETE" - }, - { - "name": "PUT" - }, - { - "name": "PATCH" - } - ] - } -}' -``` - -To access the `/sample-app/python/hello` endpoint, the new role -`Python_SampleApp_Application_Administrator` must be assigned to any -client accessing the endpoint. diff --git a/app.Dockerfile b/app.Dockerfile new file mode 100644 index 0000000..6dca988 --- /dev/null +++ b/app.Dockerfile @@ -0,0 +1,25 @@ +FROM + +ARG USER_ID=60577 +ARG USER_NAME="eric-sdk" +ARG APP_VERSION +LABEL \ + adp.app.version=$APP_VERSION + +WORKDIR /code + +COPY ./eric-oss-hello-world-python-app ./eric-oss-hello-world-python-app +COPY requirements.txt . + +RUN chmod +x ./eric-oss-hello-world-python-app/main.py + +RUN pip install --upgrade pip + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +RUN echo "$USER_ID:x:$USER_ID:0:An Identity for $USER_NAME:/nonexistent:/bin/false" >>/etc/passwd +RUN echo "$USER_ID:!::0:::::" >>/etc/shadow + +USER $USER_ID + +CMD ["./eric-oss-hello-world-python-app/main.py"] \ No newline at end of file diff --git a/charts/eric-oss-hello-world-python-app/eric-product-info.yaml b/charts/eric-oss-hello-world-python-app/eric-product-info.yaml index 4e13db1..a18d153 100644 --- a/charts/eric-oss-hello-world-python-app/eric-product-info.yaml +++ b/charts/eric-oss-hello-world-python-app/eric-product-info.yaml @@ -9,7 +9,7 @@ images: name: "eric-oss-hello-world-python-app" tag: "VERSION" eric-oss-hello-world-python-app-envoy: - productName: "Envoy for hello world sample app" + productName: "Envoy for Python Hello World App" productNumber: "" registry: "armdocker.rnd.ericsson.se" repoPath: "REPO_PATH" diff --git a/charts/eric-oss-hello-world-python-app/templates/configmap/envoy-configmap.yaml b/charts/eric-oss-hello-world-python-app/templates/configmap/envoy-configmap.yaml index 757d2c6..ead96c9 100644 --- a/charts/eric-oss-hello-world-python-app/templates/configmap/envoy-configmap.yaml +++ b/charts/eric-oss-hello-world-python-app/templates/configmap/envoy-configmap.yaml @@ -2,7 +2,14 @@ apiVersion: v1 kind: ConfigMap metadata: - name: {{ include "eric-oss-hello-world-python-app.name" . }}-envoy-template + name: {{ include "eric-oss-hello-world-python-app.name" . }}-envoy-configmap + labels: + {{- include "eric-oss-hello-world-python-app.labels" . | indent 4 }} + {{- if .Values.labels }} + {{ .Values.labels | toYaml | indent 4 }} + {{- end }} + annotations: + {{- include "eric-oss-hello-world-python-app.product-info" . | indent 4 }} data: ENVOY_CONFIG_FILE: |- static_resources: @@ -40,13 +47,12 @@ data: common_tls_context: tls_certificates: - certificate_chain: - filename: {{ printf "%s/%s" (default $.Values.instantiationDefaults.envoyAppCertMountPath $.Values.envoyAppCertMountPath) (default $.Values.instantiationDefaults.envoyAppCertFileName $.Values.envoyAppCertFileName) | quote }} + filename: {{ printf "%s/%s" (default $.Values.instantiationDefaults.proxyAppCertMountPath $.Values.proxyAppCertMountPath) (default $.Values.instantiationDefaults.appCertFileName $.Values.appCertFileName) | quote }} private_key: - filename: {{ printf "%s/%s" (default $.Values.instantiationDefaults.envoyAppCertMountPath $.Values.envoyAppCertMountPath) (default $.Values.instantiationDefaults.envoyAppKeyFileName $.Values.envoyAppKeyFileName) | quote }} + filename: {{ printf "%s/%s" (default $.Values.instantiationDefaults.proxyAppCertMountPath $.Values.proxyAppCertMountPath) (default $.Values.instantiationDefaults.appKeyFileName $.Values.appKeyFileName) | quote }} validation_context: trusted_ca: - filename: {{ printf "%s/%s" (default $.Values.instantiationDefaults.envoyPlatformCaCertMountPath $.Values.envoyPlatformCaCertMountPath) (default $.Values.instantiationDefaults.envoyPlatformCaCertFileName $.Values.envoyPlatformCaCertFileName) | quote }} - + filename: {{ printf "%s/%s" (default $.Values.instantiationDefaults.proxyCaCertMountPath $.Values.proxyCaCertMountPath) (default $.Values.instantiationDefaults.platformCaCertFileName $.Values.platformCaCertFileName) | quote }} # Plain HTTP listener for other endpoints - name: listener_http address: diff --git a/charts/eric-oss-hello-world-python-app/templates/deployment/deployment.yaml b/charts/eric-oss-hello-world-python-app/templates/deployment/deployment.yaml index 54aadbb..7f3bf0c 100644 --- a/charts/eric-oss-hello-world-python-app/templates/deployment/deployment.yaml +++ b/charts/eric-oss-hello-world-python-app/templates/deployment/deployment.yaml @@ -57,12 +57,10 @@ spec: path: logcontrol.json - name: envoy-config configMap: - name: {{ include "eric-oss-hello-world-python-app.name" . }}-envoy-template + name: {{ include "eric-oss-hello-world-python-app.name" . }}-envoy-configmap items: - key: ENVOY_CONFIG_FILE path: envoy.yaml - - name: envoy-config-dir - emptyDir: {} - name: platform-cacerts secret: secretName: {{ index .Values "platformCaCertSecretName" | quote }} @@ -75,13 +73,13 @@ spec: secret: secretName: {{ include "eric-oss-hello-world-python-app.clientSecret" . | quote }} defaultMode: 420 - - name: envoy-platform-cacerts + - name: proxy-platform-cacerts secret: - secretName: {{ index .Values "envoyPlatformCaCertSecretName" | quote }} + secretName: {{ index .Values "platformCaCertSecretName" | quote }} defaultMode: 420 - - name: envoy-app-certs + - name: proxy-app-certs secret: - secretName: {{ index .Values "envoyAppSecretName" | quote }} + secretName: {{ index .Values "appSecretName" | quote }} defaultMode: 420 containers: - name: eric-oss-hello-world-python-app @@ -198,7 +196,7 @@ spec: {{- end }} resources: {{- toYaml .Values.resources.helloWorld | nindent 12 }} - - name: envoy + - name: envoy-proxy image: {{ template "eric-oss-hello-world-python-app.imagePath" (dict "imageId" "eric-oss-hello-world-python-app-envoy" "values" .Values "files" .Files) }} imagePullPolicy: {{ include "eric-oss-hello-world-python-app.registryImagePullPolicy" . | quote }} securityContext: @@ -217,13 +215,8 @@ spec: drop: - all {{- include "eric-oss-hello-world-python-app.seccomp-profile" . | indent 12 }} - command: ["/bin/sh", "-c"] - args: - - | - echo "==== Dumping envoy config ====" - cat /etc/envoy/envoy.yaml - echo "==== Starting Envoy ====" - exec envoy -c /etc/envoy/envoy.yaml --log-level info --base-id 1 + command: ["envoy"] + args: ["-c", "/etc/envoy/envoy.yaml", "--base-id", "1"] ports: - name: envoy-http containerPort: 8080 @@ -234,49 +227,42 @@ spec: livenessProbe: tcpSocket: port: 8443 - {{- if (index .Values "probes" "envoy" "livenessProbe" "initialDelaySeconds") }} - {{ print "initialDelaySeconds: " (index .Values "probes" "envoy" "livenessProbe" "initialDelaySeconds") }} + {{- if (index .Values "probes" "proxy" "livenessProbe" "initialDelaySeconds") }} + {{ print "initialDelaySeconds: " (index .Values "probes" "proxy" "livenessProbe" "initialDelaySeconds") }} {{- end }} - {{- if (index .Values "probes" "envoy" "livenessProbe" "failureThreshold") }} - {{ print "failureThreshold: " (index .Values "probes" "envoy" "livenessProbe" "failureThreshold") }} + {{- if (index .Values "probes" "proxy" "livenessProbe" "failureThreshold") }} + {{ print "failureThreshold: " (index .Values "probes" "proxy" "livenessProbe" "failureThreshold") }} {{- end }} - {{- if (index .Values "probes" "envoy" "livenessProbe" "periodSeconds") }} - {{ print "periodSeconds: " (index .Values "probes" "envoy" "livenessProbe" "periodSeconds") }} + {{- if (index .Values "probes" "proxy" "livenessProbe" "periodSeconds") }} + {{ print "periodSeconds: " (index .Values "probes" "proxy" "livenessProbe" "periodSeconds") }} {{- end }} - {{- if (index .Values "probes" "envoy" "livenessProbe" "timeoutSeconds") }} - {{ print "timeoutSeconds: " (index .Values "probes" "envoy" "livenessProbe" "timeoutSeconds") }} + {{- if (index .Values "probes" "proxy" "livenessProbe" "timeoutSeconds") }} + {{ print "timeoutSeconds: " (index .Values "probes" "proxy" "livenessProbe" "timeoutSeconds") }} {{- end }} readinessProbe: tcpSocket: port: 8443 - {{- if (index .Values "probes" "envoy" "readinessProbe" "initialDelaySeconds") }} - {{ print "initialDelaySeconds: " (index .Values "probes" "envoy" "readinessProbe" "initialDelaySeconds") }} + {{- if (index .Values "probes" "proxy" "readinessProbe" "initialDelaySeconds") }} + {{ print "initialDelaySeconds: " (index .Values "probes" "proxy" "readinessProbe" "initialDelaySeconds") }} {{- end }} - {{- if (index .Values "probes" "envoy" "readinessProbe" "failureThreshold") }} - {{ print "failureThreshold: " (index .Values "probes" "envoy" "readinessProbe" "failureThreshold") }} + {{- if (index .Values "probes" "proxy" "readinessProbe" "failureThreshold") }} + {{ print "failureThreshold: " (index .Values "probes" "proxy" "readinessProbe" "failureThreshold") }} {{- end }} - {{- if (index .Values "probes" "envoy" "readinessProbe" "periodSeconds") }} - {{ print "periodSeconds: " (index .Values "probes" "envoy" "readinessProbe" "periodSeconds") }} + {{- if (index .Values "probes" "proxy" "readinessProbe" "periodSeconds") }} + {{ print "periodSeconds: " (index .Values "probes" "proxy" "readinessProbe" "periodSeconds") }} {{- end }} - {{- if (index .Values "probes" "envoy" "readinessProbe" "timeoutSeconds") }} - {{ print "timeoutSeconds: " (index .Values "probes" "envoy" "readinessProbe" "timeoutSeconds") }} + {{- if (index .Values "probes" "proxy" "readinessProbe" "timeoutSeconds") }} + {{ print "timeoutSeconds: " (index .Values "probes" "proxy" "readinessProbe" "timeoutSeconds") }} {{- end }} - env: - - name: ENVOY_APP_CERT_FULL_PATH - value: {{ printf "%s/%s" (default .Values.instantiationDefaults.envoyAppCertMountPath .Values.envoyAppCertMountPath) .Values.envoyAppCertFileName }} - - name: ENVOY_APP_KEY_FULL_PATH - value: {{ printf "%s/%s" (default .Values.instantiationDefaults.envoyAppCertMountPath .Values.envoyAppCertMountPath) .Values.envoyAppKeyFileName }} - - name: ENVOY_CA_CERT_FULL_PATH - value: {{ printf "%s/%s" (default .Values.instantiationDefaults.envoyPlatformCaCertMountPath .Values.envoyPlatformCaCertMountPath) .Values.envoyPlatformCaCertFileName }} volumeMounts: - name: envoy-config mountPath: /etc/envoy readOnly: true - - name: envoy-platform-cacerts - mountPath: {{ index .Values "envoyPlatformCaCertMountPath" | default .Values.instantiationDefaults.envoyPlatformCaCertMountPath | quote }} + - name: proxy-platform-cacerts + mountPath: {{ index .Values "proxyCaCertMountPath" | default .Values.instantiationDefaults.proxyCaCertMountPath | quote }} readOnly: true - - name: envoy-app-certs - mountPath: {{ index .Values "envoyAppCertMountPath" | default .Values.instantiationDefaults.envoyAppCertMountPath | quote }} + - name: proxy-app-certs + mountPath: {{ index .Values "proxyAppCertMountPath" | default .Values.instantiationDefaults.proxyAppCertMountPath | quote }} readOnly: true {{- if include "eric-oss-hello-world-python-app.pullSecrets" . }} imagePullSecrets: diff --git a/charts/eric-oss-hello-world-python-app/templates/service/service.yaml b/charts/eric-oss-hello-world-python-app/templates/service/service.yaml index 0188b1c..b1f5b80 100644 --- a/charts/eric-oss-hello-world-python-app/templates/service/service.yaml +++ b/charts/eric-oss-hello-world-python-app/templates/service/service.yaml @@ -3,24 +3,24 @@ kind: Service metadata: name: {{ include "eric-oss-hello-world-python-app.name" . }} labels: - {{- include "eric-oss-hello-world-python-app.labels" . | indent 4 }} + {{- include "eric-oss-hello-world-python-app.labels" . | nindent 4 }} {{- if .Values.labels }} - {{ .Values.labels | toYaml | indent 4 }} + {{- toYaml .Values.labels | nindent 4 }} {{- end }} annotations: -{{- include "eric-oss-hello-world-python-app.product-info" . | indent 4 }} + {{- include "eric-oss-hello-world-python-app.product-info" . | nindent 4 }} spec: type: {{ .Values.service.type }} {{- if .Values.global.internalIPFamily }} ipFamilies: [{{ .Values.global.internalIPFamily }}] {{- end }} ports: - - port: {{ .Values.service.httpport }} - targetPort: 8080 + - port: {{ index .Values.service "http-port" }} + targetPort: {{ .Values.service.httpTargetPort | default 8080 }} protocol: TCP name: envoy-http - - port: {{ .Values.service.httpsport }} - targetPort: 8443 + - port: {{ index .Values.service "https-port" }} + targetPort: {{ .Values.service.httpsTargetPort | default 8443 }} protocol: TCP name: envoy-https selector: diff --git a/charts/eric-oss-hello-world-python-app/values.yaml b/charts/eric-oss-hello-world-python-app/values.yaml index c891431..0eb9ce8 100644 --- a/charts/eric-oss-hello-world-python-app/values.yaml +++ b/charts/eric-oss-hello-world-python-app/values.yaml @@ -43,20 +43,8 @@ seccompProfile: service: type: ClusterIP - httpport: 8080 - httpsport: 8443 - -ingress: - enabled: false - ingressClass: OAM-IngressClass - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - host: "" - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local + http-port: 8080 + https-port: 8443 resources: helloWorld: @@ -109,12 +97,23 @@ probes: eric-oss-hello-world-python-app: livenessProbe: failureThreshold: 3 - initialDelaySeconds: 60 + initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 10 readinessProbe: failureThreshold: 3 - initialDelaySeconds: 60 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 10 + proxy: + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 10 + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 10 envoy: @@ -139,11 +138,8 @@ instantiationDefaults: platformCaCertMountPath: "/etc/tls-ca/platform/" appCertMountPath: "/etc/tls/log/" clientCredsMountPath: "/etc/client-creds/" - envoyPlatformCaCertMountPath: "/etc/certs/ca" - envoyAppCertMountPath: "/etc/certs/app" - #envoyPlatformCaCertFileName: "dummy1.crt" - #envoyAppCertFileName: "dummy2.crt" - #envoyAppKeyFileName: "dummy3.key" + proxyCaCertMountPath: "/etc/certs/ca" + proxyAppCertMountPath: "/etc/certs/app" global: clientCredentials: diff --git a/docker-compose.yaml b/docker-compose.yaml index 6a35154..930dea8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,27 +1,21 @@ -version: "3.9" - services: app: build: context: . - dockerfile: Dockerfile.app + dockerfile: app.Dockerfile args: - APP_VERSION: ${APP_VERSION} + APP_VERSION: ${VERSION} image: ${APP_IMAGE} - container_name: eric-oss-hello-world-python-app ports: - "8050:8050" - restart: unless-stopped envoy: build: context: . - dockerfile: Dockerfile.envoy + dockerfile: envoy.Dockerfile image: ${ENVOY_IMAGE} - container_name: envoy depends_on: - app ports: - "8080:8080" - "8443:8443" - restart: unless-stopped \ No newline at end of file diff --git a/envoy.Dockerfile b/envoy.Dockerfile new file mode 100644 index 0000000..7d37bd4 --- /dev/null +++ b/envoy.Dockerfile @@ -0,0 +1,6 @@ +FROM envoyproxy/envoy:distroless-v1.35.0 + +USER 60577:60577 +EXPOSE 8080 8443 + +CMD ["envoy", "-c", "/etc/envoy/envoy.yaml"] diff --git a/eric-oss-hello-world-python-app/main.py b/eric-oss-hello-world-python-app/main.py index eda2a0d..acd3adb 100755 --- a/eric-oss-hello-world-python-app/main.py +++ b/eric-oss-hello-world-python-app/main.py @@ -62,7 +62,7 @@ def health(): indicate that the application is healthy. """ self.update_session() - self.logger.log("200 OK: Health check", Severity.DEBUG) + self.logger.log("200 OK: Health check", Severity.INFO) return "Ok\n" def update_session(self):