シークレットの管理
ボールト・シークレット、シークレット・タグおよびシークレット・ルールを作成および管理します。
OCIクラウド・サービスを使用することが重要であるため、デジタル・ボールトにシークレットを格納、取得および管理することが重要です。シークレットには、OCIサービスおよびシステムへの接続に使用するパスワード、証明書、SSHキーまたは認証トークンを指定できます。OCI Vaultにシークレットを格納すると、コードまたは構成ファイルに格納するよりもセキュリティが高くなります。アプリケーションはOCIシークレット管理と通信して、シークレットを取得し、ターゲット・サービスに接続します。
Oracle Cloud Infrastructure Secret Managementでは、シークレットを使用して、APIキー、パスワード、暗号化キーなどの機密データを簡単に保護できます。これらのシークレットを安全に作成、格納、管理およびアクセスするための堅牢なソリューションを提供します。提供される一元化されたストレージでは、ハードウェア・セキュリティ・モジュール(HSM)と詳細なアクセス制御を利用して、重要な情報のセキュリティと整合性を保護します。OCIシークレット管理を使用して、アプリケーションにシークレットを直接埋め込むことをなくし、攻撃対象領域を減らし、アプリケーション全体のセキュリティを強化します。
シークレットの自動生成およびローテーション
シークレットが生成されると、定期的に更新されます。シークレットは手動で更新することも、自動的に設定することもできます。シークレットの自動生成およびローテーションは、シークレットを手動で設定し、スクリプトを使用してローテーションする際の負担を軽減しますが、かわりに、シークレットの作成、ローテーションおよび削除から効率的に管理する方法を提供します。
シークレットの自動生成機能では、シークレット生成用のテンプレートの使用がサポートされています。自動シークレット・ローテーションを使用すると、1か月から12か月までのシークレット間隔を設定できます。この機能は、Autonomous Databaseおよびファンクション・サービスと統合され、Autonomous Databaseまたはファンクション・コードで使用されるシークレットを更新できます。OCI Functionsでは、シークレットの自動ローテーションにより、資格証明を簡単にローテーションし、ローテーション・プロセスの一部としてコードを実行できます。自動化シークレットのローテーション機能は、手動で作成したシークレットにも使用できます。
シークレットのリージョン間レプリケーション
シークレットは最大3つの宛先リージョンにレプリケートできます。レプリカは読取り専用であり、ソース・シークレットに加えられた変更を継承します。詳細は、シークレットのレプリケートを参照してください。
自動シークレット・ローテーションを使用する利点
- セキュリティの強化: シークレットを定期的に更新すると、漏洩した資格証明によるデータ侵害の影響が最小限に抑えられます。
- 運用効率: シークレットの作成、回転などの手動タスクを自動化することで、時間と効率が節約されます。
- 規制コンプライアンス: 秘密のローテーションと自動化のコンプライアンスを規制する多くの基準に準拠します。
- 人的ミスの削減: 反復的なタスクを自動化することで、人的ミスの可能性が軽減され、セキュリティが強化されます。
シークレット生成
パスフレーズ、SSHキーおよびバイトのシークレットを生成できます。OCI Vaultが生成するすべてのシークレットは、FIPSおよびセキュリティに準拠しています。OCIコンソール、APIまたはCLIを使用してシークレットを生成できます。シークレットを生成する場合は、シークレット・コンテキストを指定し、シークレット・テンプレートを定義する必要があります。シークレット・コンテキストは、シークレットのシークレット・タイプおよび構造を定義します。選択したシークレット・タイプに基づいて、Vaultは様々なシークレット生成テンプレートをサポートしています。
PASSPHRASE
: 最大32文字の長さのパスワードを生成します。OCI Databaseサービスのデフォルト・パスワードの場合、最大文字長は30です。SSH_KEY
: 長さ2048、3072および4096のRSAキー・ペアを生成します。秘密鍵はPKCS#8 PEM形式で格納され、公開鍵はX.509 PEM形式で格納されます。BYTES
: FIPS苦情バイナリ・シークレットである512バイトと1024バイトを生成します。バイトはbase64コードです。
シークレット・タイプおよびデフォルト・テンプレート
PASSPHRASE
- サポートされているテンプレート:
SECRETS_DEFAULT_PASSWORD
およびDBAAS_DEFAULT_PASSWORD
- シークレット・テンプレートのプレースホルダ:
%GENERATED_PASSPHRASE%
- 例:
{"user": "abc", "pwd": "%GENERATED_PASSPHRASE%"}
- サポートされているテンプレート:
-
SSH_KEY
- サポートされているテンプレート:
RSA_2048
、RSA_3072
、RSA_4096
- シークレット・テンプレートのプレースホルダ:
%GENERATED_PUBLIC_KEY%
、%GENERATED_PRIVATE_KEY%
- 例:
{"publicKey": "%GENERATED_PRIVATE_KEY%", "privateKey": "%GENERATED_PRIVATE_KEY%"} → {"publicKey": "-----BEGIN PUBLIC KEY-----\nBase64 encoded public key\n-----END PUBLIC KEY-----", "privateKey":"-----BEGIN PRIVATE KEY-----\nBase64 encoded private key\n-----END PRIVATE KEY-----"}
- サポートされているテンプレート:
BYTES
- サポートされているテンプレート:
BYTES_512
、BYTES_1024
- シークレット・テンプレートのプレースホルダ:
%GENERATED_BYTES%
- 例:
{"host": "abc", "hostLuksKey": "%GENERATED_BYTES%"} → {"host": "abc", "hostLuksKey": "generatedbyteshere=="}
- サポートされているテンプレート:
シークレット・バージョンおよびローテーション状態
ボールト・シークレット・バージョン、ローテーション状態およびシークレット・バージョン制限の影響について学習します。
ボールト・シークレット・バージョンおよびローテーション状態について理解することで、制限、ローテーションや他のルール、または規制への準拠を保つようにシークレット・コンテンツをトラッキングおよび管理できます。
シークレットのバージョンおよびローテーション状態を含む、シークレットの概念の基本を学習するには、キーおよびシークレット管理の概念に関する項を参照してください。シークレット・バージョンの作業の詳細は、シークレットの管理を参照してください。
回転関数
ローテーション機能は、シークレット・サービスのシークレットのローテーションを担当します。ローテーション関数の4つのステップについて学習し、サンプル関数ハンドラ・コードを参照するには、次の項を展開します。
ローテーション関数には、次の4つのステップが含まれています。
VERIFY_CONNECTION
: シークレットに格納されている既存の資格証明を使用して、ターゲット・システムへの接続を検証します。CREATE_PENDING_VERSION
: シークレットに新しい保留中のシークレット・バージョンを作成します。UPDATE_TARGET_SYSTEM
: 2番目のステップで作成した保留中のシークレット・バージョンに格納されている資格証明でターゲット・システムを更新します。PROMOTE_PENDING_VERSION
: シークレットの状態をpendingからcurrentに更新します。
関数ハンドラ:
ファンクション・ハンドラには、ステップ・パラメータに基づいて適切な回転ステップをコールするロジックが含まれている必要があります。これは、IF ELSE条件文またはswitch caseを使用して実行できます。無効なステップ・パラメータが指定されている場合、関数ハンドラはエラーを生成します。
入力:
ファンクション・ハンドラは、単一のパラメータSecretRotationInput
を必要とします。secretRotationInput
は、secretId(String)、step(String)およびcurrentVersionNo(Long)など、ローテーションに必要なパラメータを含むPOJO (Plain-old java object)です。
- secretId: シークレット識別子またはOCID
- ステップ:ローテーション・ステップ(
VERIFY_CONNECTION
、CREATE_PENDING_VERSION
、UPDATE_TARGET_SYSTEM
またはPROMOTE_PENDING_VERSION
のいずれかである必要があります) - currentVersionNo:
CURRENT
シークレット・バージョンの番号
SecretRotationInputポジョ
@Getter
@Setter
@ToString(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@AllArgsConstructor
@Builder(toBuilder = true)
public static class SecretRotationInput {
private String step;
private Long versionNo;
private String secretId;
}
サンプル関数ハンドラコード:
public static class SecretRotationOutput {
int responseCode;
Long currentVersionNo;
String returnMessage;
}
public SecretRotationOutput handleRequest(SecretRotationInput input) {
switch(input.getStep()) {
case "VERIFY_CONNECTION":
return verifyConnection(input.getSecretId());
case "CREATE_PENDING_VERSION":
return createNewPendingVersion(input.getSecretId());
case "UPDATE_TARGET_SYSTEM":
return updateTargetSystem(input.getSecretId(), input.getVersionNo());
case "PROMOTE_PENDING_VERSION":
return promotePendingVersion(input.getSecretId(), input.getVersionNo());
default:
log.error("Secret Rotation: invalid rotation step");
return SecretRotationOutput.builder()
.responseCode(400)
.currentVersionNo(null)
.returnMessage("INVALID STEP")
.build();
}
}
ステップ1: VERIFY_CONNECTION
このステップでは、ターゲット・システムへの接続を検証します。
- 入力: このメソッドは、パラメータ
SecretId
のみを想定しています。 - 出力: このメソッドは
SecretRotationOutput
を出力します。 - ロジック: このファンクションは、まず
PENDING
バージョンをフェッチし、それとの接続を検証しようとします。これは、以前の再試行がPENDING
バージョンの昇格に失敗したが、バージョンがシステムに正常に適用された失敗シナリオを処理します。成功した場合は、成功レスポンスを返します。失敗した場合は、現在のバージョンをフェッチして接続を確認します。成功した場合は、現在のバージョン番号とともに成功レスポンス・コードを返します。成功しない場合は、エラーを返します。
VERIFY_CONNECTIONの疑似コード
pseudo code for verifyConnection:
Check if "PENDING" secret version exists
If it exist, verify connection
If succeeds, then return success.
Fetch the "CURRENT" secret version
Verify connection with "CURRENT" secret version
If succeeds, return success and the current version number in the response.
If not, return SecretRotationOutput with appropriate error code and message.
ステップ2: CREATE_PENDING_VERSION
新しい保留中のシークレット・バージョンを生成します。
- 入力: このメソッドは、
secretId
パラメータも受け入れます。 - 出力: このメソッドは
SecretRotationOutput
を出力します。 -
ロジック: このメソッドは、最初に
PENDING
状態のシークレット・バージョンが存在するかどうかをチェックします。存在しない場合は、新しいPENDING
シークレット・バージョンが生成されます。ただし、ステップがすでに存在する場合は、成功レスポンスが返されます。シークレット・メタデータ・フィールドを使用して、シークレット構造に関する追加の詳細を格納し、新しいシークレット・バージョンの作成時に同じ構造を使用することもできます。シークレット・サービスの自動生成機能を使用して、シークレット・コンテンツを自動生成することもできます。自動生成を使用すると、より汎用的な関数を記述できます。
CREATE_PENDING_VERSIONの疑似コード
pseudo code for createPendingVersion:
Try to get the pending version
If it succeeds, return success
Else create a new secret version in "PENDING" state and then return success
サンプル・コード:
// Constructor
public void constructorClass() {
secretsDpClient = SecretsClient.builder()
.region(region)
.configuration(configuration)
.build(auth_provider);
secretsCpClient = VaultsClient.builder()
.region(region)
.configuration(configuration)
.build(auth_provider);
}
private String createNewPassword() {
// This method must contains the logic to generate the new secret content
}
private SecretRotationOutput createNewPendingVersion(SecretRotationInput input) {
// Make sure the given secret exist
Secret secret = secretsCpClient.getSecret(GetSecretRequest.builder()
.secretId(input.getSecretId())
.build()).getSecret();
// Now try to get the pending secret version, if that fails, create a new one
try {
GetSecretBundleRequest getSecretBundleRequest = GetSecretBundleRequest.builder()
.secretId(input.getSecretId())
.stage(GetSecretBundleRequest.Stage.Pending)
.build();
secretsDpClient.getSecretBundle(getSecretBundleRequest);
return SecretRotationOutput.builder()
.responseCode(200)
.returnMessage("Successfully retrieved the pending secret version")
.build();
} catch (BmcException bmc) {
// Create a new pending version
UpdateSecretDetails updateSecretDetails = secret.getIsAutoGenerationEnabled() ? UpdateSecretDetails.builder()
.secretContent(Base64SecretContentDetails.builder()
.stage(SecretContentDetails.Stage.Pending)
.build())
.build() : UpdateSecretDetails.builder()
.secretContent(Base64SecretContentDetails.builder()
.content(createNewPassword())
.stage(SecretContentDetails.Stage.Pending)
.build())
.build();
secretsCpClient.updateSecret(UpdateSecretRequest.builder()
.secretId(input.getSecretId())
.updateSecretDetails(updateSecretDetails)
.build()).getSecret();
log.info("Successfully added a new version with 'PENDING' stage for secretId {}", input.getSecretId());
return SecretRotationOutput.builder()
.responseCode(200)
.returnMessage("Pending version created successfully")
.currentVersionNo(input.getVersionNo())
.build();
}
}
ステップ3: UPDATE_TARGET_SYSTEM
ターゲット・システムで保留中のシークレットを設定します。
- 入力: このメソッドは、
currentVersionNo
およびsecretId
を受け入れます。 - 出力: このメソッドは、
SecretRotationOutput
も出力します。 - ロジック: このメソッドは、まず
PENDING
シークレット・バージョンを使用してターゲット・システムへのログインを試行し、成功時に戻ります。これは、前の再試行が保留バージョンの昇格に失敗したが、バージョンがシステムに正常に適用された失敗シナリオも処理します。失敗した場合は、CURRENT
シークレット・バージョンでログインしようとします。現在のシークレット・バージョンが成功すると、ターゲット・システムのユーザー・パスワードとしてPENDING
パスワードが設定されます。
UPDATE_TARGET_SYSTEMの疑似コード
Pseudo code for updateTargetSystem:
Fetch the "PENDING" secret version
Check the connection with Pending version
It it works return success and the pending version number in the response
Fetch the "CURRENT" secret version
Check the connection with it
If it works
Update the target system with "PENDING" version
Verify that target system is updated.
if yes then return success and the pending version number in the response
else return the appropriate error code and the error message
If not, return SecretRotationOutput with appropriate error code and message.
サンプル・コード:
private SecretRotationOutput updateTargetSystem(String secretId, Long currentVersionNo) {
// Get the pending secret version
SecretBundle pendingSecretBundle = secretsDpClient.getSecretBundle(GetSecretBundleRequest.builder()
.secretId(secretId)
.stage(GetSecretBundleRequest.Stage.Pending)
.build()).getSecretBundle();
// First try to login with the pending secret, if it succeeds, return
Connection conn = getConnection(pendingSecretBundle);
if(conn) {
log.info("Updated the target system with pending version");
return SecretRotationOutput.builder()
.responseCode(200)
.returnMessage("Successfully update target service")
.currentVersionNo(pendingSecretBundle.getVersionNumber())
.build();
}
SecretBundle currentSecretBundle = secretsDpClient.getSecretBundle(GetSecretBundleRequest.builder()
.versionNumber(currentVersionNo)
.secretId(secretId)
.build()).getSecretBundle();
conn = getConnection(currentSecretBundle);
if(conn) {
// Write logic to update the target system and check the connection with the updated password
} else {
log.error("Unable to log into system using the current version");
return SecretRotationOutput.builder()
.returnMessage("Unable to log into system using the current version")
.responseCode(400)
.build();
}
}
ステップ4: PROMOTE_PENDING_VERSION
保留中のシークレットを現在のシークレットとしてマークして、ローテーションを終了します。
- 入力: このメソッドは、
currentVersionNo
およびsecretId
を受け入れます。 - 出力: このメソッドは、
SecretRotationOutput
も出力します。 - ロジック: シークレット・サービスをコールして、
PENDING
バージョンをCURRENT
にプロモートします。UpdateRequest
では、CURRENT
に昇格する必要があるバージョンを指定する必要があります。
PROMOTE_PENDING_VERSIONの疑似コード
pseudo code for promotePendingVersion:
Make updateSecret Api call to promote the specified version to "CURRENT"
サンプル・コード:
private SecretRotationOutput promotePendingVersion(String secretId, Long versionNo) {
try {
Secret secret = secretsCpClient.updateSecret(UpdateSecretRequest.builder()
.secretId(secretId)
.updateSecretDetails(UpdateSecretDetails.builder()
.currentVersionNumber(versionNo)
.build())
.opcRequestId(UUID.randomUUID().toString())
.build()).getSecret();
log.info("Successfully promoted the version number {} to 'CURRENT'", versionNo);
return SecretRotationOutput.builder()
.responseCode(200)
.currentVersionNo(secret.getCurrentVersionNumber())
.returnMessage("Successfully promoted the pending version")
.build();
} catch (BmcException bmc) {
log.error("Fail to promote the pending version. SecretId: {}, pendingVersionNo: {}. {}", secretId, versionNo, bmc.getMessage());
return SecretRotationOutput.builder()
.returnMessage(bmc.getMessage())
.responseCode(bmc.getStatusCode())
.build();
}
}
ローテーション状態
シークレット・バージョンは、一度に複数のローテーション状態になることができます。1つのシークレット・バージョンのみが存在する場合(シークレットを初めて作成したときなど)、そのシークレット・バージョンは自動的に「現在」と「最新」の両方としてマークされます。最新バージョンのシークレットには、最後にボールトにアップロードされたシークレット・コンテンツが含まれます。最近アップロードされたシークレット・マテリアルがあるシークレット・バージョンを検索する必要がある場合は、「最新」ステータスを使用してこれを実行できます。
シークレット・ローテーション用に新しいシークレット・コンテンツをアップロードする場合、シークレット・バージョンを「保留中」としてマークできます。これにより、シークレット・マテリアルをすぐに使用可能にせずにボールトにアップロードできます。保留中のシークレット・バージョンが現在のステータスにプロモートする準備ができるまで、「現在」シークレット・バージョンを使用し続けることができます。通常は、最初にターゲット・リソースまたはサービス上で資格証明をローテーションした後、これを行います。シークレット・ローテーションが、シークレットに依存するアプリケーションおよびリソースに及ぼす影響を考慮する必要があることに注意してください。現在のシークレット・バージョンを変更すると、それを必要とするアプリケーションが期待されるシークレット・バージョンをボールトから取得できなくなる可能性があります。
シークレット・バージョンは、「前」としてマークすることもできます。これにより、シークレットを以前のバージョンに簡単にロールバックできます。シークレットが誤ってローテーションされた場合、または古いシークレット・バージョンを使用して再開する必要があるリソースのバックアップをリストアする場合に、これを行う必要がある場合があります。「前」としてマークされたシークレット・バージョンは、最新のローテーションの直前に「現在」としてマークされたバージョンです。以前のバージョンにロールバックするには、シークレットを更新して、目的のシークレット・バージョン番号を指定します。
シークレット・バージョンが削除されていないかぎり、シークレットを更新して、その過去のシークレット・バージョンを使用できます。シークレットを更新すると、選択するシークレット・バージョン番号を「現在」としてマークします。これは、シークレット・バージョンを「現在」にプロモートするのと同じ結果になります。
削除できるのは、「非推奨」としてマークされているシークレット・バージョンだけです。非推奨のシークレット・バージョンとは、「現在」、「保留中」、「前」のいずれとしてもマークされていないバージョンです。これにより、削除されたシークレット・バージョンが後で必要になるような状況(たとえば、前にバックアップされたデータベースをリストアする場合)を回避できます。「非推奨」以外のマークが付いているシークレット・バージョンは、「現在」としてマークして、再びアクティブに使用できます。
バージョン制限
シークレット・バージョンの制限は、使用中のシークレット・バージョンと非推奨のバージョン(削除がスケジュールされているバージョンを含む)の両方に適用されます。特定のシークレット・バージョンの数、およびテナンシ内のシークレット・バージョンの制限の詳細は、サービス制限に関する項を参照してください。
開始する前に
開始する前に、まずシークレット・ルールおよびシークレット・バージョンおよびローテーション状態を読んで、ルール、シークレット・バージョンおよびシークレット・バージョン・ローテーション状態の作業の意味をよく理解することをお薦めします。
必須IAMポリシー
Oracle Cloud Infrastructureを使用するには、管理者が、テナンシ管理者がポリシーでセキュリティ・アクセス権を付与したグループのメンバーである必要があります。コンソールまたは(SDK、CLIまたはその他のツールを使用した) REST APIのどれを使用しているかにかかわらず、このアクセス権が必要です。権限がない、または認可されていないというメッセージが表示された場合は、テナンシ管理者に、どのタイプのアクセス権があり、どのコンパートメントでアクセスが作業する必要があるかを管理者に確認してください。
管理者向け:
- セキュリティ管理者によるボールト、キーおよびシークレットの管理のポリシーを使用すると、指定したグループは、ボールト、キーおよびシークレットに関するすべての操作を実行できます。
- 暗号化キーを有効にするポリシーの作成ポリシーにより、指定したグループは特定のボールト内のシークレットですべてを実行できます。
- ユーザーによるすべてのシークレットの読取り、更新およびローテーションのポリシーを使用すると、指定したグループは、テナンシの任意のボールト内のすべてのシークレットの読取り、更新およびローテーションを行うことができます。
- 権限の詳細、またはシークレットのより詳細なポリシーを記述する方法については、ボールト・サービスの詳細を参照してください。
ポリシーを初めて使用する場合は、アイデンティティ・ドメインの管理および共通ポリシーを参照してください。
シークレットのタグ付け
リソースにタグを適用すると、ビジネス・ニーズに応じた整理に役立ちます。リソースの作成時にタグを適用できます。また、後でリソースを更新して、タグを追加、改訂または削除できます。タグ適用についての一般情報は、リソース・タグを参照してください。
リソースのモニタリング
別のコンパートメントへのリソースの移動
シークレットはコンパートメント間で移動できます。シークレットを新しいコンパートメントに移動した後、コンパートメントに構成されたポリシーは即座に適用され、シークレットおよびシークレット・バージョンへのアクセスに影響します。シークレットを移動しても、シークレットに関連付けられているボールトへのアクセスには影響しません。同様に、ボールトは、そのシークレットの移動とは別に、コンパートメント間で移動できます。詳細は、コンパートメントの管理を参照してください。