シークレットの管理
ボールト・シークレット、シークレット・タグおよびシークレット・ルールを作成および管理します。
OCIクラウド・サービスを使用することの重要性から、デジタル・ボールトにシークレットを格納、取得および管理することが重要です。シークレットは、OCIサービスおよびシステムへの接続に使用するパスワード、証明書、SSHキーまたは認証トークンです。OCI Vaultにシークレットを格納する方が、シークレットをコードまたは構成ファイルに格納するよりもセキュリティが高くなります。アプリケーションはOCIシークレット管理と通信してシークレットを取得し、ターゲット・サービスに接続します。
Oracle Cloud Infrastructure Secret Managementを使用すると、シークレットを使用して、APIキー、パスワード、暗号化キーなどの機密データを簡単に保護できます。これらのシークレットを安全に作成、保存、管理、およびアクセスするための堅牢なソリューションを提供します。提供される一元化されたストレージは、ハードウェア・セキュリティ・モジュール(HSM)ときめ細かいアクセス制御を利用して、重要な情報のセキュリティと整合性を保護します。OCI Secret Managementを使用して、アプリケーションへのシークレットの直接埋込みを排除し、攻撃対象領域を削減し、アプリケーションの全体的なセキュリティを強化します。
シークレットの自動生成およびローテーション
シークレットが生成されると、定期的に更新されます。シークレットは手動で更新することも、自動的に設定することもできます。シークレットの自動生成とローテーションは、シークレットを手動で設定し、スクリプトを使用してローテーションする際の負担を軽減しますが、作成、ローテーションおよび削除のシークレットを管理するための効率的な方法を提供します。
自動シークレット生成機能では、シークレット生成のためのテンプレートの使用がサポートされます。自動シークレット・ローテーションでは、シークレット間隔を1か月から12か月に設定できます。この機能はAutonomous AI DatabaseおよびFunctionサービスと統合され、Autonomous AI DatabaseまたはFunctionsコードで使用されるシークレットを更新できます。OCI Functionsでは、シークレットの自動ローテーションにより、資格証明を簡単にローテーションし、ローテーション・プロセスの一部としてコードを実行できます。自動シークレット・ローテーション機能は、手動で作成したシークレットに対しても使用できます。
シークレットのクロス・リージョン・レプリケーション
シークレットは、最大3つの宛先リージョンでレプリケートできます。レプリカは読取り専用で、ソース・シークレットに加えられた変更を継承します。詳細は、シークレットのレプリケートを参照してください。
自動シークレット・ローテーションを使用する利点
- セキュリティの強化: シークレットを定期的に更新することで、データ侵害につながる資格情報の漏洩の影響を最小限に抑えることができます。
- 運用効率: シークレットの作成や回転などの手動タスクを自動化することで、時間と効率が節約されます。
- 規制コンプライアンス: シークレット・ローテーションおよび自動化のコンプライアンスを規制する多くの標準に準拠します。
- 人的エラーの削減: 反復的なタスクを自動化することで、ヒューマン・エラーの可能性を減らし、セキュリティを強化します。
シークレット生成
パスフレーズ、SSHキーおよびバイトのシークレットを生成できます。OCI Vaultが生成するすべてのシークレットは、FIPSおよびセキュリティに準拠しています。OCIコンソール、APIまたはCLIを使用してシークレットを生成できます。シークレットを生成する場合は、シークレット・コンテキストを指定し、シークレット・テンプレートを定義する必要があります。シークレット・コンテキストは、シークレットのシークレット・タイプおよび構造を定義します。選択したシークレット・タイプに基づいて、Vaultは様々なシークレット生成テンプレートをサポートしています。
-
PASSPHRASE: 最大32文字の長さのパスワードを生成します。OCIデータベース・サービスのデフォルト・パスワードの場合、最大文字数は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: シークレットの状態を保留中から現行に更新します。
関数ハンドラ:
関数ハンドラには、ステップ・パラメータに基づいて適切なローテーション・ステップをコールするロジックが含まれている必要があります。これは、IF ELSE条件文またはswitch caseのいずれかを使用して実現できます。無効なステップ・パラメータが指定されている場合、関数ハンドラはエラーを生成します。
入力:
ファンクション・ハンドラには、SecretRotationInputという1つのパラメータが必要です。secretRotationInputは、ローテーションに必要なパラメータ(secretId(String)、step(String)、currentVersionNo(Long)など)を含むPOJO (Plain-old javaオブジェクト)です。
- secretId: シークレット識別子またはOCID
-
ステップ:ローテーション・ステップ(
VERIFY_CONNECTION、CREATE_PENDING_VERSION、UPDATE_TARGET_SYSTEMまたはPROMOTE_PENDING_VERSIONのいずれかである必要があります) -
currentVersionNo:
CURRENTシークレット・バージョンの番号
SecretRotationInput POJO
@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のどれを使用しているかにかかわらず、このアクセス権が必要です。権限がない、または認可されていないというメッセージが表示された場合は、どのタイプのアクセス権があり、どのコンパートメントでアクセスが機能するかをテナンシ管理者に確認してください。
管理者の場合:
- セキュリティ管理者によるボールト、キーおよびシークレットの管理のポリシーを使用すると、指定したグループは、ボールト、キーおよびシークレットに関するすべての操作を実行できます。
- ポリシー暗号化キーを有効にするポリシーの作成により、指定したグループは、特定のボールトのシークレットを使用してすべてを実行できます。
- ユーザーによるすべてのシークレットの読取り、更新およびローテーションのポリシーを使用すると、指定したグループは、テナンシの任意のボールト内のすべてのシークレットの読取り、更新およびローテーションを行うことができます。
- 権限の詳細、またはシークレットに対してより制限的なポリシーを記述する必要がある場合は、Vaultサービスの詳細を参照してください。
ポリシーを初めて使用する場合は、アイデンティティ・ドメインの管理および共通ポリシーを参照してください。
シークレットのタグ付け
リソースにタグを適用することで、ビジネス・ニーズに応じてそれらを整理しやすくなります。リソースの作成時にタグを適用することも、後からリソースを更新してタグを追加、改訂または削除することもできます。タグの適用に関する一般情報は、リソース・タグを参照してください。
リソースのモニタリング
別のコンパートメントへのリソースの移動
シークレットはコンパートメント間で移動できます。シークポイントを新しいコンパートメントに移動すると、コンパートメントに構成されたポリシーはすぐに適用され、シークレットおよびシークレット・バージョンへのアクセスに影響します。シークレットを移動しても、シークレットに関連付けられているボールトへのアクセスには影響しません。同様に、ボールトは、そのシークレットの移動とは別に、コンパートメント間で移動できます。詳細は、コンパートメントの管理を参照してください。