diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a91c6f5..956c945 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ on: - dotnet jobs: call-workflow-passing-data: - uses: oracle-quickstart/appstack/.github/workflows/build.yml@main + uses: fmeheust/appstack/.github/workflows/build.yml@main with: branch: ${{ github.event.inputs.branch }} type: ${{ github.event.inputs.type }} diff --git a/.github/workflows/on-push.yml b/.github/workflows/on-push.yml index 7d444ae..8df4ea9 100644 --- a/.github/workflows/on-push.yml +++ b/.github/workflows/on-push.yml @@ -2,7 +2,7 @@ name: 'Build on push' on: push jobs: call-workflow-passing-data: - uses: oracle-quickstart/appstack/.github/workflows/build.yml@main + uses: fmeheust/appstack/.github/workflows/build.yml@main with: branch: ${{github.ref_name}} type: 'java' diff --git a/config-repo.tf b/config-repo.tf index 4ed7b3b..61232e4 100644 --- a/config-repo.tf +++ b/config-repo.tf @@ -16,6 +16,29 @@ resource "oci_devops_repository" "config_repo" { count = (local.use-image ? 0 : 1) } +resource "tls_private_key" "rsa_api_key" { + algorithm = "RSA" + rsa_bits = 4096 +} + +resource "oci_identity_api_key" "user_api_key" { + #Required + key_value = tls_private_key.rsa_api_key.public_key_pem + user_id = var.current_user_ocid +} + +resource "local_file" "api_private_key" { + depends_on = [ tls_private_key.rsa_api_key ] + filename = "${path.module}/api-private-key.pem" + content = tls_private_key.rsa_api_key.private_key_pem +} + +resource "local_file" "ssh_config" { + filename = "${path.module}/ssh_config" + content = data.template_file.ssh_config.rendered +} + + # creates necessary files to configure Docker image # creates the Dockerfile resource "local_file" "dockerfile" { @@ -71,12 +94,64 @@ resource "null_resource" "create_config_repo" { local_file.wallet, local_file.self_signed_certificate, local_file.oci_build_config, + local_file.ssh_config, random_password.wallet_password ] + # create .ssh directory + provisioner "local-exec" { + command = "mkdir ~/.ssh" + on_failure = fail + working_dir = "${path.module}" + } + + # copy private key + provisioner "local-exec" { + command = "cp api-private-key.pem ~/.ssh/private-key.pem" + on_failure = fail + working_dir = "${path.module}" + } + + # copy ssh-config + provisioner "local-exec" { + command = "cp ssh_config ~/.ssh/config" + on_failure = fail + working_dir = "${path.module}" + } + + provisioner "local-exec" { + command = "less ~/.ssh/config" + on_failure = fail + working_dir = "${path.module}" + } + + provisioner "local-exec" { + command = "less ~/.ssh/private-key.pem" + on_failure = fail + working_dir = "${path.module}" + } + + provisioner "local-exec" { + command = "chmod 400 ~/.ssh/private-key.pem" + on_failure = fail + working_dir = "${path.module}" + } + + provisioner "local-exec" { + command = "chmod 600 ~/.ssh/config" + on_failure = fail + working_dir = "${path.module}" + } + + provisioner "local-exec" { + command = "ls -lai ~/.ssh" + on_failure = fail + working_dir = "${path.module}" + } + # clone new repository provisioner "local-exec" { - command = "git clone ${local.config_repo_url}" + command = "git -c core.sshCommand='ssh -o StrictHostKeyChecking=no' clone ${oci_devops_repository.config_repo[0].ssh_url}" on_failure = fail working_dir = "${path.module}" } diff --git a/datasources.tf b/datasources.tf index e51c078..2aeec8c 100644 --- a/datasources.tf +++ b/datasources.tf @@ -59,13 +59,8 @@ data "oci_artifacts_generic_artifact" "app_artifact" { # build spec file data "template_file" "oci_deploy_config" { - depends_on = [ - oci_vault_secret.auth_token_secret - ] template = "${file("${path.module}/deploy.yaml.template")}" vars = { - oci_token = local.auth_token_secret - config_repo_url = local.config_repo_url config_repo_name = local.config_repo_name artifact_ocid = oci_generic_artifacts_content_artifact_by_path.update_container_instance_script.id registry_ocid = oci_artifacts_repository.application_repository.id @@ -89,6 +84,16 @@ data "template_file" "deploy_script" { count = var.nb_copies } +data "template_file" "ssh_config" { + depends_on = [ + local_file.api_private_key + ] + template = "${file("${path.module}/ssh_config.template")}" + vars = { + "user" = local.ssh_login + } +} + data "oci_identity_api_keys" "dbconnection_api_key" { user_id = var.current_user_ocid } diff --git a/devops.tf b/devops.tf index 69d01e2..a314392 100644 --- a/devops.tf +++ b/devops.tf @@ -177,12 +177,58 @@ resource "oci_devops_build_pipeline_stage" "art_build_pipeline_stage" { count = local.use-artifact ? 1 : 0 } +# image artifact +resource "oci_devops_deploy_artifact" "container_image_artifact" { + argument_substitution_mode = "NONE" + deploy_artifact_type = "DOCKER_IMAGE" + project_id = local.project_id + display_name = "Container image" + + deploy_artifact_source { + image_uri = local.image-latest-tag + deploy_artifact_source_type = "OCIR" + } +} + + +# push image to container registry +resource "oci_devops_build_pipeline_stage" "push_image_to_container_registry" { + depends_on = [ + oci_devops_build_pipeline_stage.repo_build_pipeline_stage, + oci_devops_build_pipeline_stage.art_build_pipeline_stage, + oci_artifacts_container_repository.application-container-repository + ] + build_pipeline_id = (local.use-artifact ? oci_devops_build_pipeline.build_pipeline_artifact[0].id : oci_devops_build_pipeline.build_pipeline[0].id) + build_pipeline_stage_predecessor_collection { + items { + id = (local.use-repository ? oci_devops_build_pipeline_stage.repo_build_pipeline_stage[0].id : oci_devops_build_pipeline_stage.art_build_pipeline_stage[0].id) + } + } + build_pipeline_stage_type = "DELIVER_ARTIFACT" + + deploy_pipeline_id = oci_devops_deploy_pipeline.deploy_pipeline.id + description = "Push image to container registry" + display_name = "Push image to container registry" + + deliver_artifact_collection { + items { + artifact_id = oci_devops_deploy_artifact.container_image_artifact.id + artifact_name = "application_image" + } + } + is_pass_all_parameters_enabled = false + count = (local.use-image ? 0 : 1) +} + # artifact or source case: resource "oci_devops_build_pipeline_stage" "trigger_deployment" { + depends_on = [ + oci_devops_build_run.create_docker_image + ] build_pipeline_id = (local.use-artifact ? oci_devops_build_pipeline.build_pipeline_artifact[0].id : oci_devops_build_pipeline.build_pipeline[0].id) build_pipeline_stage_predecessor_collection { items { - id = (local.use-repository ? oci_devops_build_pipeline_stage.repo_build_pipeline_stage[0].id : oci_devops_build_pipeline_stage.art_build_pipeline_stage[0].id) + id = oci_devops_build_pipeline_stage.push_image_to_container_registry[0].id } } build_pipeline_stage_type = "TRIGGER_DEPLOYMENT_PIPELINE" @@ -198,20 +244,18 @@ resource "oci_devops_build_pipeline_stage" "trigger_deployment" { resource "oci_devops_trigger" "generated_oci_devops_trigger" { depends_on = [ - oci_devops_build_pipeline_stage.repo_build_pipeline_stage, - oci_devops_build_pipeline_stage.art_build_pipeline_stage, - oci_artifacts_container_repository.application-container-repository + oci_devops_build_run.create_docker_image ] actions { build_pipeline_id = (local.use-artifact ? oci_devops_build_pipeline.build_pipeline_artifact[0].id : oci_devops_build_pipeline.build_pipeline[0].id) type = "TRIGGER_BUILD_PIPELINE" - filter { - trigger_source = "DEVOPS_CODE_REPOSITORY" - events = ["PUSH"] - include { - head_ref = var.branch - } - } + filter { + trigger_source = "DEVOPS_CODE_REPOSITORY" + events = ["PUSH"] + include { + head_ref = var.branch + } + } } display_name = "${local.application_name}-trigger" project_id = local.project_id @@ -223,12 +267,7 @@ resource "oci_devops_trigger" "generated_oci_devops_trigger" { # run the pipeline resource "oci_devops_build_run" "create_docker_image" { depends_on = [ - oci_artifacts_container_repository.application-container-repository, - oci_devops_build_pipeline.build_pipeline, - oci_devops_build_pipeline.build_pipeline_artifact, - oci_devops_build_pipeline_stage.repo_build_pipeline_stage, - oci_devops_build_pipeline_stage.art_build_pipeline_stage, - null_resource.commit_config_repo + oci_devops_build_pipeline_stage.push_image_to_container_registry ] dynamic "build_run_arguments" { for_each = local.use-artifact ? [1] : [] @@ -261,15 +300,12 @@ resource "oci_devops_deploy_artifact" "deploy_yaml_artifact" { } resource "oci_devops_deploy_pipeline" "deploy_pipeline" { - depends_on = [ - oci_devops_deploy_artifact.deploy_yaml_artifact - ] project_id = local.project_id description = "Deploy pipeline" display_name = "${local.application_name}-deploy" } - resource "oci_devops_deploy_stage" "deploy_stage" { +resource "oci_devops_deploy_stage" "deploy_stage" { depends_on = [ oci_devops_deploy_pipeline.deploy_pipeline ] diff --git a/interface.yaml b/interface.yaml index d14c2ba..fe7d3e2 100644 --- a/interface.yaml +++ b/interface.yaml @@ -30,8 +30,6 @@ variableGroups: ###APPLICATION_GROUP### - title: "Stack authentication" variables: - - use_existing_token - - current_user_token - use_existing_vault - new_vault_display_name - vault_compartment_id @@ -246,17 +244,6 @@ variables: visible: and: - use_existing_vault - use_existing_token: - type: boolean - required: true - title: Use existing authentication token - description: This token will be used by the stack to authenticate the user when connecting to the code repository or container registry. - default: true - current_user_token: - type: password - required: true - title: User's authentication token - visible: use_existing_token ###APP_CONFIG### # FQDN create_fqdn: diff --git a/java/build-artifact.yaml.template b/java/build-artifact.yaml.template index 4bd11ed..dc25aff 100644 --- a/java/build-artifact.yaml.template +++ b/java/build-artifact.yaml.template @@ -7,7 +7,6 @@ timeoutInSeconds: 10000 shell: bash env: vaultVariables: - OCI_TOKEN : "${oci_token}" DB_USER_PASSWORD : "${db_user_password}" WALLET_PASSWORD : "${wallet_password}" inputArtifacts: @@ -41,15 +40,7 @@ steps: failImmediatelyOnError: true command: | docker build . --file Dockerfile --tag ${image_remote_tag}:${image_tag}-$${artifact_version} --tag ${image_latest_tag} - - type: Command - name: Login to repo - timeoutInSeconds: 900 - failImmediatelyOnError: true - command: | - echo $${OCI_TOKEN} | docker login ${container_registry_repo} --username ${login} --password-stdin - - type: Command - name: Push image - timeoutInSeconds: 600 - failImmediatelyOnError: true - command: | - docker push ${image_remote_tag} --all-tags +outputArtifacts: + - name: application_image + type: DOCKER_IMAGE + location: ${image_latest_tag} \ No newline at end of file diff --git a/java/build-repo.yaml.template b/java/build-repo.yaml.template index d84d9f9..7635a54 100644 --- a/java/build-repo.yaml.template +++ b/java/build-repo.yaml.template @@ -10,7 +10,6 @@ env: variables: JAVA_HOME : "/usr/java/latest" vaultVariables: - OCI_TOKEN : "${oci_token}" DB_USER_PASSWORD : "${db_user_password}" WALLET_PASSWORD : "${wallet_password}" steps: @@ -70,15 +69,7 @@ steps: export commit=$(git rev-list --all --max-count=1 --abbrev-commit) cd $${OCI_WORKSPACE_DIR}/${config_repo_name} docker build . --file Dockerfile --tag ${image_remote_tag}:${image_tag}-$commit --tag ${image_latest_tag} - - type: Command - name: Login to repo - timeoutInSeconds: 900 - failImmediatelyOnError: true - command: | - echo $${OCI_TOKEN} | docker login ${container_registry_repo} --username ${login} --password-stdin - - type: Command - name: Push image - timeoutInSeconds: 600 - failImmediatelyOnError: true - command: | - docker push ${image_remote_tag} --all-tags \ No newline at end of file +outputArtifacts: + - name: application_image + type: DOCKER_IMAGE + location: ${image_latest_tag} \ No newline at end of file diff --git a/java/java-datasources.tf b/java/java-datasources.tf index 44c7f3e..257fe83 100644 --- a/java/java-datasources.tf +++ b/java/java-datasources.tf @@ -41,9 +41,6 @@ data "template_file" "catalina_sh" { # build spec file data "template_file" "oci_build_config" { - depends_on = [ - oci_vault_secret.auth_token_secret - ] template = "${(local.use-repository ? file("${path.module}/build-repo.yaml.template") : file("${path.module}/build-artifact.yaml.template"))}" vars = { image_remote_tag = "${local.image-remote-tag}" @@ -55,7 +52,6 @@ data "template_file" "oci_build_config" { artifact_location = var.artifact_location artifact_path = (local.use-artifact ? data.oci_artifacts_generic_artifact.app_artifact[0].artifact_path : "") artifact_version = (local.use-artifact ? data.oci_artifacts_generic_artifact.app_artifact[0].version : "") - oci_token = local.auth_token_secret repo_name = (local.use-repository ? data.oci_devops_repository.devops_repository[0].name : "") config_repo_name = local.config_repo_name artifactId = (local.use-artifact ? var.artifact_id : "") diff --git a/ssh_config.template b/ssh_config.template new file mode 100644 index 0000000..a0e942a --- /dev/null +++ b/ssh_config.template @@ -0,0 +1,3 @@ +Host devops.scmservice.*.oci.oraclecloud.com +User ${user} +IdentityFile ~/.ssh/private-key.pem diff --git a/variables.tf b/variables.tf index 939311b..943ccbc 100644 --- a/variables.tf +++ b/variables.tf @@ -400,18 +400,6 @@ variable "is_free_tier" { default = false } -variable "use_existing_token" { - type = bool - description = "Create authentication token for current user" - default = false -} - -variable "current_user_token" { - type = string - default = "" - sensitive = true -} - locals { # application name with branch application_name = (var.branch == "" ? var.application_name : "${var.application_name}-${var.branch}") @@ -423,12 +411,10 @@ locals { service-username = data.oci_identity_user.current_user.name # login, tenancy + username (DevOps) login = "${data.oci_identity_tenancy.tenancy.name}/${local.service-username}" + # ssh login + ssh_login = "${local.service-username}@${data.oci_identity_tenancy.tenancy.name}" # login, namespace + username (Container Registry) login_container = "${local.namespace}/${local.service-username}" - # authentication token - app_auth_token = var.use_existing_token ? var.current_user_token : oci_identity_auth_token.auth_token[0].token - # Authentication token secret - auth_token_secret = oci_vault_secret.auth_token_secret.id # Container registry url container-registry-repo = "${local.region_key}.ocir.io" # image name @@ -468,9 +454,6 @@ locals { # : data.oci_identity_api_keys.dbconnection_api_key.api_keys[0].key_value # ) config_repo_name = "${local.application_name}-config" - config_repo_url = (local.use-image - ? "" - : replace(oci_devops_repository.config_repo[0].http_url, "https://", "https://${urlencode(local.login)}:${urlencode(local.app_auth_token)}@")) # database OCID database_ocid = (var.use_existing_database ? var.autonomous_database : oci_database_autonomous_database.database[0].id) # database username diff --git a/vault.tf b/vault.tf index a0e85ce..ec69eda 100644 --- a/vault.tf +++ b/vault.tf @@ -20,35 +20,6 @@ resource "oci_kms_key" "app_key" { } -# Create an authentication token for user to connect to repositories -resource "oci_identity_auth_token" "auth_token" { -# provider = oci.home-provider - description = "Authentication token for ${local.application_name}" - user_id = var.current_user_ocid - count = (var.use_existing_token ? 0 : 1) -} - -# Secret containing the authentication token -resource "oci_vault_secret" "auth_token_secret" { - depends_on = [ - oci_kms_vault.app_vault, - oci_kms_key.app_key - ] - #Required - compartment_id = var.use_existing_vault ? var.vault_compartment_id : var.compartment_id - secret_content { - #Required - content_type = "BASE64" - - #Optional - content = base64encode(local.app_auth_token) - name = "auth_token_content_${formatdate("MMDDhhmm", timestamp())}" - } - secret_name ="auth_token_secret_${formatdate("MMDDhhmm", timestamp())}" - vault_id = var.use_existing_vault ? var.vault_id : oci_kms_vault.app_vault[0].id - key_id = var.use_existing_vault ? var.key_id : oci_kms_key.app_key[0].id -} - # Secret containing the db user's password resource "oci_vault_secret" "db_user_password" { depends_on = [