다음을 통해 공유


Azure Key Vault를 사용하여 MicroProfile 구성

이 자습서에서는 MicroProfile 구성 API를 사용하여 Azure Key Vault에서 비밀을 검색하도록 MicroProfile 애플리케이션을 구성하는 방법을 보여 줍니다. 개발자는 구성 데이터를 검색하고 마이크로 서비스에 삽입하기 위한 개방형 표준 MicroProfile Config API의 이점을 누릴 수 있습니다.

필수 조건

  • Azure 구독; Azure 구독이 아직 없는 경우 MSDN 구독자 혜택을 활성화하거나 무료 계정에 등록할 수 있습니다.
  • Unix와 유사한 환경을 위한 Azure CLI. 이 문서에는 Azure CLI의 Bash 변형만 필요합니다.
    • 코드에서 사용하기 전에 Azure CLI를 설치하고 az login 명령을 사용하여 DefaultAzureCredential 대화형으로 로그인하여 Azure에 로그인합니다.
      az login
      
    • 이 문서에는 Azure CLI 버전 2.61.0 이상이 필요합니다. Azure Cloud Shell을 사용하는 경우 최신 버전이 이미 설치되어 있습니다.
  • Azure Cloud Shell에는 이러한 모든 필수 구성 요소가 미리 설치되어 있습니다. 자세한 내용은 Azure Cloud Shell 빠른 시작을 참조하세요.
  • Azure Cloud Shell을 사용하는 대신 이 가이드의 명령을 로컬로 실행하는 경우 다음 단계를 완료합니다.
    • Unix와 비슷한 운영 체제가 설치된 로컬 컴퓨터를 준비합니다(예: Ubuntu, macOS 또는 Linux용 Windows 하위 시스템).
    • Java SE 구현 버전 17 이상을 설치합니다(예: OpenJDK의 Microsoft 빌드).
    • Maven 3.9.8 이상을 설치합니다.
    • cURL을 설치합니다.

Azure Key Vault와 MicroProfile 구성 연결

Azure Key Vault와 MicroProfile Config API를 결합하는 기능을 간단히 살펴보겠습니다. 다음은 주석이 추가된 클래스의 필드 코드 조각입니다 @Inject @ConfigProperty. name 주석에 지정된 이름은 Azure Key Vault에서 조회할 비밀의 이름이며defaultValue, 비밀이 검색되지 않은 경우 사용됩니다. Azure Key Vault에 저장된 비밀 값 또는 이러한 비밀이 없는 경우 기본값은 런타임 시 필드에 자동으로 삽입됩니다. 이러한 방식으로 속성 값을 삽입하면 다양한 이점이 제공됩니다. 예를 들어 생성자 및 setter 메서드에서 값을 전달할 필요가 없으며 구성이 코드에서 외부화됩니다. 가장 강력한 이점 중 하나는 개발, 테스트 및 prod 환경에 대해 별도의 값 집합을 갖는 것입니다.

@Inject
@ConfigProperty(name = "key-name", defaultValue = "Unknown")
String keyValue;

다음 예제와 같이 MicroProfile 구성에 명령적으로 액세스할 수도 있습니다.

public class DemoClass {
    @Inject
    Config config;

    public void method() {
        System.out.println("Hello: " + config.getValue("key-name", String.class));
    }
}

이 샘플에서는 MicroProfile의 Open Liberty 구현을 사용합니다. 호환되는 구현의 전체 목록은 MicroProfile 호환 구현을 참조 하세요. 이 샘플에서는 Azure에서 애플리케이션을 컨테이너화하고 실행하는 방법도 보여 줍니다.

이 샘플에서는 MicroProfile Key Vault 사용자 지정 ConfigSource 라이브러리에 대해 낮은 마찰 Azure 확장을 사용합니다. 이 라이브러리에 대한 자세한 내용은 라이브러리 추가 정보를 참조 하세요.

Azure Key Vault 리소스 만들기부터 시작하여 로컬 컴퓨터에서 이 코드를 실행하는 데 필요한 단계는 다음과 같습니다.

Azure Key Vault 리소스 만들기

Azure CLI를 사용하여 Azure Key Vault 리소스를 만들고 두 개의 비밀로 채웁니다.

먼저 Azure에 로그인하고 구독을 현재 활성 구독으로 설정합니다.

az login
az account set --subscription <subscription-id>

다음으로, 고유한 이름(예 : mp-kv-rg-ejb010424)을 사용하여 리소스 그룹을 만듭니다.

export RESOURCE_GROUP_NAME=mp-kv-rg-ejb010424
az group create \
    --name ${RESOURCE_GROUP_NAME} \
    --location eastus

이제 고유한 이름(예 : kvejb010424)으로 Azure Key Vault 리소스를 만들고, 두 개의 비밀을 추가하고, Key Vault URI를 환경 변수로 내보냅니다.

export KEY_VAULT_NAME=kv-ejb010424
az keyvault create \
    --resource-group "${RESOURCE_GROUP_NAME}" \
    --name "${KEY_VAULT_NAME}" \
    --location eastus \
    --enable-rbac-authorization false

az keyvault secret set \
    --vault-name "${KEY_VAULT_NAME}" \
    --name secret \
    --value 1234
az keyvault secret set \
    --vault-name "${KEY_VAULT_NAME}" \
    --name anotherSecret \
    --value 5678

export AZURE_KEYVAULT_URL=$(az keyvault show \
    --resource-group "${RESOURCE_GROUP_NAME}" \
    --name "${KEY_VAULT_NAME}" \
    --query properties.vaultUri \
    --output tsv)
echo $AZURE_KEYVAULT_URL

환경 변수 AZURE_KEYVAULT_URL 는 나중에 샘플에서 작동하도록 라이브러리를 구성하는 데 필요합니다. 터미널을 열어 두고 나중에 로컬로 앱을 실행하는 데 사용합니다.

정말 간단하죠. 이제 Azure에서 두 개의 비밀로 Key Vault를 실행하고 있습니다. 이제 샘플 리포지토리를 복제하고 앱에서 이 리소스를 사용하도록 구성할 수 있습니다.

로컬로 시작 및 실행

이 예제는 GitHub에서 사용할 수 있는 샘플 애플리케이션을 기반으로 합니다. 이전에 연 터미널로 전환하고 다음 명령을 실행하여 리포지토리를 복제하고 로컬로 앱을 실행합니다.

git clone https://github.com/Azure/azure-microprofile.git
cd azure-microprofile
git checkout 1.0.0-beta.3
cd integration-tests/open-liberty-sample
mvn clean package liberty:run

메시지가 You are in 'detached HEAD' state표시되면 이 메시지는 무시해도 안전합니다.

참고 항목

라이브러리는 기본 Azure 자격 증명을 사용하여 Azure에서 인증합니다.

Azure CLI az login 명령을 통해 계정을 로컬로 DefaultAzureCredential 인증했으므로 해당 계정으로 인증하여 Azure Key Vault에 액세스합니다.

와 유사한 The defaultServer server is ready to run a smarter planet출력이 표시될 때까지 기다립니다. 새 터미널을 열고 다음 명령을 실행하여 샘플을 테스트합니다.

# Get the value of secret "secret" stored in the Azure key vault. You should see 1234 in the response.
echo $(curl -s http://localhost:9080/config/value/secret -X GET)

# Get the value of secret "anotherSecret" stored in the Azure key vault. You should see 5678 in the response.
echo $(curl -s http://localhost:9080/config/value/anotherSecret -X GET)

# Get the names of secrets stored in the Azure key vault. You should see ["anotherSecret","secret"] in the response.
echo $(curl -s http://localhost:9080/config/propertyNames -X GET)

# Get the name-value paris of secrets stored in the Azure key vault. You should see {"anotherSecret":"5678","secret":"1234"} in the response.
echo $(curl -s http://localhost:9080/config/properties -X GET)

주석에 설명된 예상 출력이 표시됩니다. 앱이 실행 중인 터미널로 다시 전환합니다. 앱을 중지하려면 Ctrl + C를 누릅니다.

샘플 앱 검사

MicroProfile Config가 일반적으로 작동하는 방식과 특히 MicroProfile Key Vault 사용자 지정 ConfigSource 라이브러리가 작동하는 방식을 자세히 알아보겠습니다.

라이브러리 종속성

다음 Maven 종속성을 사용하여 앱에 MicroProfile Key Vault 사용자 지정 ConfigSource를 포함합니다.

<dependency>
  <groupId>com.azure.microprofile</groupId>
  <artifactId>azure-microprofile-config-keyvault</artifactId>
</dependency>

Azure Key Vault에 연결

라이브러리는 azure-microprofile-config-keyvault Azure API에 대한 직접 종속성을 도입하지 않고 앱을 Azure Key Vault에 연결합니다. 라이브러리는 Azure Key Vault에서 읽는 방법을 알고 있는 MicroProfile Config 사양 ConfigSource 인터페이스의 구현을 제공합니다. MicroProfile 구성 구현의 나머지 부분에서는 Open Liberty 런타임에서 제공합니다. 사양에 대한 링크는 다음 단계를 참조 하세요.

라이브러리는 특정 키 자격 증명 모음에 azure.keyvault.url 앱을 바인딩하는 구성 속성을 정의합니다. MicroProfile 구성 사양은 런타임에 구성 속성과 같은 azure.keyvault.url값이 검색되는 방법에 대한 "환경 변수 매핑 규칙"을 정의합니다. 이러한 규칙 중 하나는 속성이 환경 변수로 변환된다는 것을 나타냅니다. 이 속성 azure.keyvault.url 은 환경 변수 AZURE_KEYVAULT_URL 를 참조하게 합니다.

샘플 앱의 주요 클래스

이전 cURL 명령이 호출한 REST 리소스를 살펴보겠습니다. 이 REST 리소스는 프로젝트의 클래스 ConfigResource.javaintegration-tests/open-liberty-sample 정의됩니다.

@Path("/config")
public class ConfigResource {

    @Inject
    private Config config;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/value/{name}")
    public String getConfigValue(@PathParam("name") String name) {
        return config.getConfigValue(name).getValue();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/propertyNames")
    public Set<String> getConfigPropertyNames() {
        ConfigSource configSource = getConfigSource(AzureKeyVaultConfigSource.class.getSimpleName());
        return configSource.getPropertyNames();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/properties")
    public Map<String, String> getConfigProperties() {
        ConfigSource configSource = getConfigSource(AzureKeyVaultConfigSource.class.getSimpleName());
        return configSource.getProperties();
    }

    private ConfigSource getConfigSource(String name) {
        return StreamSupport.stream(config.getConfigSources().spliterator(), false)
                .filter(source -> source.getName().equals(name))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("ConfigSource not found: " + name));
    }
}

이 메서드는 getConfigValue() 삽입된 구현을 Config 사용하여 애플리케이션 구성 원본에서 값을 조회합니다. 구현에 대한 Config 모든 값 조회는 MicroProfile 구성 사양에 정의된 검색 알고리즘을 통해 찾을 수 있습니다. 라이브러리는 azure-microprofile-config-keyvault Azure Key Vault를 구성 원본으로 추가합니다.

이 메서드는 getConfigSource() 검색 알고리즘을 방지하고 속성을 확인하기 위해 바로 이동합니다 AzureKeyVaultConfigSource . 이 메서드는 및 getConfigProperties() 메서드에서 getConfigPropertyNames() 사용됩니다.

Azure Container Apps에서 실행

이 섹션에서는 앱을 컨테이너화하고, Azure Key Vault에 액세스하도록 사용자 할당 관리 ID를 구성하고, Azure Container Apps에 컨테이너화된 앱을 배포합니다.

로컬에서 앱을 실행한 터미널로 다시 전환하고 이 섹션 전체에서 사용합니다.

Azure Container Registry 설정

Azure Container Registry를 사용하여 앱을 컨테이너화하고 앱 이미지를 저장합니다.

먼저 고유한 이름(예 : acrejb010424)으로 Azure Container Registry를 만듭니다.

export ACR_NAME=acrejb010424
az acr create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $ACR_NAME \
    --sku Basic

계속하기 전에 이 명령이 반환된 후 몇 분 정도 기다립니다.

앱 컨테이너화

다음으로, 앱을 컨테이너화하고 앱 이미지를 Azure Container Registry에 푸시합니다. 샘플 앱의 경로(예 : azure-microprofile/integration-tests/open-liberty-sample)에 있는지 확인합니다.

az acr build \
    --registry ${ACR_NAME} \
    --image open-liberty-mp-azure-keyvault:latest \
    .

와 유사한 Run ID: ca1 was successful after 1m28s메시지로 끝나는 빌드 출력이 표시됩니다. 비슷한 메시지가 표시되지 않으면 계속하기 전에 문제를 해결하고 해결합니다.

다음 명령을 사용하여 나중에 Azure Container Apps에 앱을 배포할 때 이미지에 액세스하는 데 필요한 연결 정보를 검색합니다.

export ACR_LOGIN_SERVER=$(az acr show \
    --name $ACR_NAME \
    --query 'loginServer' \
    --output tsv)

사용자가 할당한 관리 ID 설정

앞에서 설명한 대로 라이브러리는 기본 Azure 자격 증명을 사용하여 Azure에서 인증합니다. Azure Container Apps에 앱을 배포할 때 환경 변수 AZURE_CLIENT_ID 를 설정하여 Azure Key Vault에 액세스할 수 있는 권한이 있고 나중에 Azure Container Apps에 할당되는 사용자 정의 관리 ID로 인증하도록 DefaultAzureCredential을 구성합니다.

먼저 다음 명령을 사용하여 고유한 이름으로 사용자 할당 관리 ID를 만듭니다(예: uamiejb010424). 자세한 내용은 사용자 할당 관리 ID 만들기를 참조하세요.

export USER_ASSIGNED_IDENTITY_NAME=uamiejb010424
az identity create \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${USER_ASSIGNED_IDENTITY_NAME}

다음으로, 다음 명령을 사용하여 Azure Key Vault에서 비밀을 가져와서 나열할 수 있는 권한을 부여합니다. 자세한 내용은 액세스 정책 할당을 참조하세요.

export USER_ASSIGNED_IDENTITY_OBJECT_ID="$(az identity show \
    --resource-group "${RESOURCE_GROUP_NAME}" \
    --name "${USER_ASSIGNED_IDENTITY_NAME}" \
    --query 'principalId' \
    --output tsv)"

az keyvault set-policy --name "${KEY_VAULT_NAME}" \
    --resource-group "${RESOURCE_GROUP_NAME}" \
    --secret-permissions get list \
    --object-id "${USER_ASSIGNED_IDENTITY_OBJECT_ID}"

성공으로 간주하려면 출력에 다음 JSON이 포함되어야 합니다.

"permissions": {
  "certificates": null,
  "keys": null,
  "secrets": [
    "list",
    "get"
  ],
  "storage": null
}

출력에 이 JSON이 포함되어 있지 않으면 계속하기 전에 문제를 해결하고 해결합니다.

그런 다음, 다음 명령을 사용하여 사용자가 할당한 관리 ID의 ID 및 클라이언트 ID를 검색하여 나중에 Azure Key Vault에 액세스하기 위해 Azure Container Apps에 할당할 수 있습니다.

export USER_ASSIGNED_IDENTITY_ID="$(az identity show \
    --resource-group "${RESOURCE_GROUP_NAME}" \
    --name "${USER_ASSIGNED_IDENTITY_NAME}" \
    --query 'id' \
    --output tsv)"
export USER_ASSIGNED_IDENTITY_CLIENT_ID="$(az identity show \
    --name "${USER_ASSIGNED_IDENTITY_NAME}" \
    --resource-group "${RESOURCE_GROUP_NAME}" \
    --query 'clientId' \
    --output tsv)"
echo $USER_ASSIGNED_IDENTITY_ID
echo $USER_ASSIGNED_IDENTITY_CLIENT_ID

Azure Container Apps에 앱 배포

앱을 컨테이너화하고 Azure Key Vault에 액세스하도록 사용자 할당 관리 ID를 구성했습니다. 이제 Azure Container Apps에 컨테이너화된 앱을 배포할 수 있습니다.

먼저 Azure Container Apps에 대한 환경을 만듭니다. Azure Container Apps의 환경은 컨테이너 앱 그룹 주위에 보안 경계를 만듭니다. 동일한 환경에 배포된 컨테이너 앱은 동일한 가상 네트워크에 배포되고 동일한 Log Analytics 작업 영역에 로그를 씁니다. 다음 예제와 같이 az containerapp env create 명령을 사용하여 고유한 이름(예: acaenvejb010424)으로 환경을 만듭니다.

export ACA_ENV=acaenvejb010424
az containerapp env create \
    --resource-group $RESOURCE_GROUP_NAME \
    --location eastus \
    --name $ACA_ENV

다음으로, 다음 예제와 같이 az containerapp create 명령을 사용하여 컨테이너 레지스트리에서 이미지를 끌어온 후 고유한 이름(예: acaappejb010424)으로 Container Apps 인스턴스를 만들어 앱을 실행합니다.

export ACA_NAME=acaappejb010424
az containerapp create \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${ACA_NAME} \
    --environment ${ACA_ENV} \
    --image ${ACR_LOGIN_SERVER}/open-liberty-mp-azure-keyvault:latest  \
    --registry-server $ACR_LOGIN_SERVER \
    --registry-identity system \
    --user-assigned ${USER_ASSIGNED_IDENTITY_ID} \
    --env-vars \
        AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} \
        AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL} \
    --target-port 9080 \
    --ingress 'external'

참고 항목

매개 변수 --user-assigned ${USER_ASSIGNED_IDENTITY_ID}를 사용하여 사용자 할당 관리 ID를 Container Apps 인스턴스에 할당합니다.

Container Apps 인스턴스는 매개 변수 --env-vars AZURE_CLIENT_ID=${USER_ASSIGNED_IDENTITY_CLIENT_ID} AZURE_KEYVAULT_URL=${AZURE_KEYVAULT_URL}에 제공된 두 개의 환경 변수를 사용하여 Azure Key Vault에 액세스할 수 있습니다. AZURE_KEYVAULT_URL 환경 변수는 MicroProfile 구성 사양에 정의된 환경 변수 매핑 규칙으로 인해 참조됩니다.

그런 다음, 다음 명령을 사용하여 앱에 액세스하기 위해 정규화된 URL을 검색합니다.

export APP_URL=https://$(az containerapp show \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${ACA_NAME} \
    --query properties.configuration.ingress.fqdn \
    --output tsv)

마지막으로 다음 명령을 다시 실행하여 Container Apps 인스턴스에서 실행되는 샘플을 테스트합니다.

# Get the value of secret "secret" stored in the Azure key vault. You should see 1234 in the response.
echo $(curl -s ${APP_URL}/config/value/secret -X GET)

# Get the value of secret "anotherSecret" stored in the Azure key vault. You should see 5678 in the response.
echo $(curl -s  ${APP_URL}/config/value/anotherSecret -X GET)

# Get the names of secrets stored in the Azure key vault. You should see ["anotherSecret","secret"] in the response.
echo $(curl -s  ${APP_URL}/config/propertyNames -X GET)

# Get the name-value paris of secrets stored in the Azure key vault. You should see {"anotherSecret":"5678","secret":"1234"} in the response.
echo $(curl -s  ${APP_URL}/config/properties -X GET)

주석에 설명된 예상 출력이 표시됩니다. 표시되지 않으면 앱이 계속 시작될 수 있습니다. 잠시 기다렸다가 다시 시도하십시오.

리소스 정리

Azure 요금을 방지하려면 불필요한 리소스를 정리해야 합니다. 리소스가 더 이상 필요하지 않은 경우 다음 명령을 실행하여 리소스를 정리합니다.

az keyvault delete \
    --resource-group "${RESOURCE_GROUP_NAME}" \
    --name "${KEY_VAULT_NAME}"

az keyvault purge \
    --name "${KEY_VAULT_NAME}" \
    --no-wait

az group delete \
    --name ${RESOURCE_GROUP_NAME} \
    --yes \
    --no-wait

다음 단계

다음 참조에서 자세히 알아볼 수 있습니다.