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

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

本文档假定您已创建 Artifact Registry Python 远程代码库PyPI 帐号。

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

所需的角色

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

如需详细了解如何授予角色,请参阅管理访问权限

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

创建 PyPI API 令牌

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

将您的 API 令牌保存为密钥版本

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

向 Artifact Registry 服务帐号授予对您的密钥的访问权限

Artifact Registry 服务代理是由 Google 代管式服务帐号,在与 Google Cloud 服务交互时代表 Artifact Registry。如需允许服务代理使用存储在 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

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

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

C#

如需向 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;
    }
}

Go

如需向 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
}

Java

如需向 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);
    }
  }
}

Node.js

如需向 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();

PHP

如需向 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);
}

Python

如需向 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}")

Ruby

如需向 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}"

API

注意:与其他示例不同,它将替换整个 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 版本。

gcloud CLI

如需使用 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 令牌的密钥版本。

远程仓库下次从上游来源发送请求以获取工件时,将使用您的凭据。