配置对 Python 软件包索引 (PyPI) 的远程代码库身份验证

本文档介绍了如何为 Artifact Registry 远程代码库配置对 Python 软件包索引 (PyPI) 上游代码库的身份验证。

本文档假定您已创建 Artifact Registry Python 远程仓库PyPI 账号。

如需详细了解远程仓库,请参阅远程仓库概览

所需的角色

如需获得为远程代码库配置对 PyPI 的身份验证所需的权限,请让管理员向您授予项目的以下 IAM 角色:

如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

您也可以通过自定义角色或其他预定义角色来获取所需的权限。

创建 PyPI API 令牌

  1. 登录 PyPI
  2. 创建 API 令牌

以 Secret 版本保存 API 令牌

  1. 在 Secret Manager 中创建 Secret
  2. 将 PyPI API 令牌保存为密钥版本

向 Artifact Registry 服务账号授予对您的 Secret 的访问权限

Artifact Registry Service Agent 在与服务交互时会代表 Artifact Registry 执行操作。 Google Cloud 如需允许服务代理使用存储在 Secret Manager 中的 Secret,您必须向服务代理授予查看 Secret 版本的权限。

服务代理标识符为:

service-PROJECT-NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

PROJECT-NUMBER 是运行 Artifact Registry 的项目的编号。 Google Cloud

如需向 Artifact Registry 服务代理授予 Secret Manager Secret Accessor 角色,请执行以下操作:

  1. 转到 Google Cloud 控制台中的 Secret Manager 页面。

    转到 Secret Manager 页面

  2. Secret Manager 页面上,点击 Secret 名称旁边的复选框。

  3. 如果面板尚未打开,请点击显示信息面板以打开面板。

  4. 在信息面板中,点击添加主账号

  5. 新主账号文本区域中,输入要添加的成员的电子邮件地址。

  6. 选择角色下拉列表中,选择 Secret Manager,然后选择 Secret Manager Secret Accessor

$ gcloud secrets add-iam-policy-binding secret-id \
    --member="member" \
    --role="roles/secretmanager.secretAccessor"

其中,memberIAM 成员,例如用户、群组或服务账号。

如需向 Artifact Registry 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


using Google.Cloud.SecretManager.V1;
using Google.Cloud.Iam.V1;

public class IamGrantAccessSample
{
    public Policy IamGrantAccess(
      string projectId = "my-project", string secretId = "my-secret",
      string member = "user:foo@example.com")
    {
        // Create the client.
        SecretManagerServiceClient client = SecretManagerServiceClient.Create();

        // Build the resource name.
        SecretName secretName = new SecretName(projectId, secretId);

        // Get current policy.
        Policy policy = client.GetIamPolicy(new GetIamPolicyRequest
        {
            ResourceAsResourceName = secretName,
        });

        // Add the user to the list of bindings.
        policy.AddRoleMember("roles/secretmanager.secretAccessor", member);

        // Save the updated policy.
        policy = client.SetIamPolicy(new SetIamPolicyRequest
        {
            ResourceAsResourceName = secretName,
            Policy = policy,
        });
        return policy;
    }
}

如需向 Artifact Registry 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

import (
	"context"
	"fmt"
	"io"

	secretmanager "cloud.google.com/go/secretmanager/apiv1"
)

// iamGrantAccess grants the given member access to the secret.
func iamGrantAccess(w io.Writer, name, member string) error {
	// name := "projects/my-project/secrets/my-secret"
	// member := "user:foo@example.com"

	// Create the client.
	ctx := context.Background()
	client, err := secretmanager.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("failed to create secretmanager client: %w", err)
	}
	defer client.Close()

	// Get the current IAM policy.
	handle := client.IAM(name)
	policy, err := handle.Policy(ctx)
	if err != nil {
		return fmt.Errorf("failed to get policy: %w", err)
	}

	// Grant the member access permissions.
	policy.Add(member, "roles/secretmanager.secretAccessor")
	if err = handle.SetPolicy(ctx, policy); err != nil {
		return fmt.Errorf("failed to save policy: %w", err)
	}

	fmt.Fprintf(w, "Updated IAM policy for %s\n", name)
	return nil
}

如需向 Artifact Registry 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1.SecretName;
import com.google.iam.v1.Binding;
import com.google.iam.v1.GetIamPolicyRequest;
import com.google.iam.v1.Policy;
import com.google.iam.v1.SetIamPolicyRequest;
import java.io.IOException;

public class IamGrantAccess {

  public static void iamGrantAccess() throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String secretId = "your-secret-id";
    String member = "user:foo@example.com";
    iamGrantAccess(projectId, secretId, member);
  }

  // Grant a member access to a particular secret.
  public static void iamGrantAccess(String projectId, String secretId, String member)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
      // Build the name from the version.
      SecretName secretName = SecretName.of(projectId, secretId);

      // Request the current IAM policy.
      Policy currentPolicy =
          client.getIamPolicy(
              GetIamPolicyRequest.newBuilder().setResource(secretName.toString()).build());

      // Build the new binding.
      Binding binding =
          Binding.newBuilder()
              .setRole("roles/secretmanager.secretAccessor")
              .addMembers(member)
              .build();

      // Create a new IAM policy from the current policy, adding the binding.
      Policy newPolicy = Policy.newBuilder().mergeFrom(currentPolicy).addBindings(binding).build();

      // Save the updated IAM policy.
      client.setIamPolicy(
          SetIamPolicyRequest.newBuilder()
              .setResource(secretName.toString())
              .setPolicy(newPolicy)
              .build());

      System.out.printf("Updated IAM policy for %s\n", secretId);
    }
  }
}

如需向 Artifact Registry 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const name = 'projects/my-project/secrets/my-secret';
// const member = 'user:you@example.com';
//
// NOTE: Each member must be prefixed with its type. See the IAM documentation
// for more information: https://cloud.google.com/iam/docs/overview.

// Imports the Secret Manager library
const {SecretManagerServiceClient} = require('@google-cloud/secret-manager');

// Instantiates a client
const client = new SecretManagerServiceClient();

async function grantAccess() {
  // Get the current IAM policy.
  const [policy] = await client.getIamPolicy({
    resource: name,
  });

  // Add the user with accessor permissions to the bindings list.
  policy.bindings.push({
    role: 'roles/secretmanager.secretAccessor',
    members: [member],
  });

  // Save the updated IAM policy.
  await client.setIamPolicy({
    resource: name,
    policy: policy,
  });

  console.log(`Updated IAM policy for ${name}`);
}

grantAccess();

如需向 Artifact Registry 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

// Import the Secret Manager client library.
use Google\Cloud\SecretManager\V1\Client\SecretManagerServiceClient;

// Import the Secret Manager IAM library.
use Google\Cloud\Iam\V1\Binding;
use Google\Cloud\Iam\V1\GetIamPolicyRequest;
use Google\Cloud\Iam\V1\SetIamPolicyRequest;

/**
 * @param string $projectId Your Google Cloud Project ID (e.g. 'my-project')
 * @param string $secretId  Your secret ID (e.g. 'my-secret')
 * @param string $member Your member (e.g. 'user:foo@example.com')
 */
function iam_grant_access(string $projectId, string $secretId, string $member): void
{
    // Create the Secret Manager client.
    $client = new SecretManagerServiceClient();

    // Build the resource name of the secret.
    $name = $client->secretName($projectId, $secretId);

    // Get the current IAM policy.
    $policy = $client->getIamPolicy((new GetIamPolicyRequest)->setResource($name));

    // Update the bindings to include the new member.
    $bindings = $policy->getBindings();
    $bindings[] = new Binding([
        'members' => [$member],
        'role' => 'roles/secretmanager.secretAccessor',
    ]);
    $policy->setBindings($bindings);

    // Build the request.
    $request = (new SetIamPolicyRequest)
        ->setResource($name)
        ->setPolicy($policy);

    // Save the updated policy to the server.
    $client->setIamPolicy($request);

    // Print out a success message.
    printf('Updated IAM policy for %s', $secretId);
}

如需向 Artifact Registry 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

def iam_grant_access(
    project_id: str, secret_id: str, member: str
) -> iam_policy_pb2.SetIamPolicyRequest:
    """
    Grant the given member access to a secret.
    """

    # Import the Secret Manager client library.
    from google.cloud import secretmanager

    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the secret.
    name = client.secret_path(project_id, secret_id)

    # Get the current IAM policy.
    policy = client.get_iam_policy(request={"resource": name})

    # Add the given member with access permissions.
    policy.bindings.add(role="roles/secretmanager.secretAccessor", members=[member])

    # Update the IAM Policy.
    new_policy = client.set_iam_policy(request={"resource": name, "policy": policy})

    # Print data about the secret.
    print(f"Updated IAM policy on {secret_id}")

如需向 Artifact Registry 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

# project_id = "YOUR-GOOGLE-CLOUD-PROJECT"  # (e.g. "my-project")
# secret_id  = "YOUR-SECRET-ID"             # (e.g. "my-secret")
# member     = "USER-OR-ACCOUNT"            # (e.g. "user:foo@example.com")

# Require the Secret Manager client library.
require "google/cloud/secret_manager"

# Create a Secret Manager client.
client = Google::Cloud::SecretManager.secret_manager_service

# Build the resource name of the secret.
name = client.secret_path project: project_id, secret: secret_id

# Get the current IAM policy.
policy = client.get_iam_policy resource: name

# Add new member to current bindings
policy.bindings << Google::Iam::V1::Binding.new(
  members: [member],
  role:    "roles/secretmanager.secretAccessor"
)

# Update IAM policy
new_policy = client.set_iam_policy resource: name, policy: policy

# Print a success message.
puts "Updated IAM policy for #{secret_id}"

注意:与其他示例不同,它将替换整个 IAM 政策。

$ curl "https://secretmanager.googleapis.com/v1/projects/project-id/secrets/secret-id:setIamPolicy" \
    --request "POST" \
    --header "authorization: Bearer $(gcloud auth print-access-token)" \
    --header "content-type: application/json" \
    --data "{\"policy\": {\"bindings\": [{\"members\": [\"member\"], \"role\": \"roles/secretmanager.secretAccessor\"}]}}"

如需详细了解如何授予或撤消对 Secret 的访问权限,请参阅管理对 Secret 的访问权限

将 PyPI 凭据添加到远程代码库

如需使用 PyPI 凭据更新远程代码库,请执行以下操作:

  1. 打开 Google Cloud 控制台中的制品库页面。

    打开“代码库”页面

  2. 在代码库列表中,选择相应代码库,然后点击修改代码库

  3. 远程代码库身份验证模式部分,更新或添加您的 PYPI 用户名 __token__ 以及包含 PyPI API 令牌的 Secret 版本。

如需使用 PyPI 凭据更新远程代码库,请运行以下命令:

gcloud artifacts repositories update REPOSITORY \
    --project=PROJECT_ID \
    --location=LOCATION \
    --remote-username=__token__ \
    --remote-password-secret-version=projects/SECRET_PROJECT_ID/secrets/SECRET_ID/versions/SECRET_VERSION

替换以下内容:

  • REPOSITORY 替换为您的 Artifact Registry 远程仓库的名称。
  • PROJECT_ID 替换为您的 Google Cloud 项目 ID。
  • LOCATION 为代码库的单区域或多区域位置。如果您设置默认值,则可以省略此标志。如需查看受支持位置的列表,请运行 gcloud artifacts locations list 命令。
  • USERNAME 替换为您的 PyPI 用户名。
  • SECRET_PROJECT_ID 替换为您创建 Secret 的项目的 ID。
  • SECRET_ID 替换为您为 Secret 指定的名称。
  • SECRET_VERSION 与您保存 PyPI API 令牌的 Secret 版本。

下次远程代码库向上游源发送工件请求时,系统会使用您的凭据。