在Go中创建KMS密钥策略

huangapple go评论82阅读模式
英文:

Create KMS key policy in Go

问题

我正在尝试使用AWS SDK v2的函数调用来创建KMS密钥:

conn := kms.NewFromConfig(cfg)

input := kms.CreateKeyInput{
	KeySpec:     types.KeySpecEccNistP521,
	KeyUsage:    types.KeyUsageTypeSignVerify,
	MultiRegion: aws.Bool(true),
    Policy:      aws.String("")
}

output, err := conn.CreateKey(ctx, &input)

我遇到的问题是我不确定如何为密钥生成策略。我猜我可以创建一个IAM策略文档的JSON,但我不想自己生成它。是否有一个可以用来生成这个文档的包或库?

英文:

I'm trying to create a KMS key using the AWS SDK v2 function call:

conn := kms.NewFromConfig(cfg)

input := kms.CreateKeyInput{
	KeySpec:     types.KeySpecEccNistP521,
	KeyUsage:    types.KeyUsageTypeSignVerify,
	MultiRegion: aws.Bool(true),
    Policy:      aws.String("")
}

output, err := conn.CreateKey(ctx, &input)

The problem I'm having is that I'm not sure how to generate the policy for the key. I assume I could create JSON for an IAM policy document, but I don't find the prospect of generating that myself to be particularly inviting. Is there a package or library that I can use to generate this document?

答案1

得分: 0

我最终创建了自己的策略结构体:

// Policy描述了一个可以用于配置IAM权限的策略文档
type Policy struct {
	Version    string       `json:"Version"`
	ID         string       `json:"Id"`
	Statements []*Statement `json:"Statement"`
}

// Statement描述了一组权限,定义了哪些资源和用户可以访问其中描述的资源
type Statement struct {
	ID            string     `json:"Sid"`
	Effect        Effect     `json:"Effect"`
	PrincipalArns Principals `json:"Principal"`
	ActionArns    Actions    `json:"Action"`
	ResourceArns  Resources  `json:"Resource"`
}

// Principals描述了与策略语句相关联的一组主体
type Principals []string

// MarshalJSON将Principals集合转换为JSON
func (p Principals) MarshalJSON() ([]byte, error) {
	// 首先,从主体列表中获取内部字符串
	var inner string
	if len(p) > 1 {
		inner = marshal(p...)
	} else if len(p) == 1 {
		inner = strings.Quote(p[0], "\"")
	} else {
		return nil, fmt.Errorf("Principal must contain at least one element")
	}

	// 接下来,创建主体块并返回
	return []byte(fmt.Sprintf("{\"AWS\": %s}", inner)), nil
}

// Actions描述了可能由主体对策略语句中描述的资源执行或不执行的一组操作
type Actions []Action

// MarshalJSON将Actions集合转换为JSON
func (a Actions) MarshalJSON() ([]byte, error) {
	// 首先,从操作列表中获取内部字符串
	var inner string
	if len(a) > 1 {
		inner = marshal(a...)
	} else if len(a) == 1 {
		inner = strings.Quote(string(a[0]), "\"")
	} else {
		return nil, fmt.Errorf("Action must contain at least one element")
	}

	// 接下来,创建操作块并返回
	return []byte(inner), nil
}

// Resources描述了策略语句影响的一组资源
type Resources []string

// MarshalJSON将Resources集合转换为JSON
func (r Resources) MarshalJSON() ([]byte, error) {
	// 首先,从资源列表中获取内部字符串
	var inner string
	if len(r) > 1 {
		inner = marshal(r...)
	} else if len(r) == 1 {
		inner = strings.Quote(r[0], "\"")
	} else {
		return nil, fmt.Errorf("Resource must contain at least one element")
	}

	// 接下来,创建资源块并返回
	return []byte(inner), nil
}

// marshal是一个将项目列表转换为JSON字符串的辅助函数
func marshal(items ...string) string {
	return "[" + strings.Join(items, ",") + "]"
}

// Effect描述策略语句对资源和描述的操作的影响
type Effect string

var (
	// Allow允许将资源和操作授权给策略语句中描述的主体
	Allow = Effect("Allow")

	// Deny拒绝策略语句中描述的主体对资源和操作的访问
	Deny = Effect("Deny")
)

// Action描述针对特定AWS资源可以执行的有效操作
type Action string

// 描述AWS可用的各种操作类型
var (
	CancelKeyDeletion                   = Action("kms:CancelKeyDeletion")
	ConnectCustomKeyStore               = Action("kms:ConnectCustomKeyStore")
	CreateAlias                         = Action("kms:CreateAlias")
	CreateCustomKeyStore                = Action("kms:CreateCustomKeyStore")
	CreateGrant                         = Action("kms:CreateGrant")
	CreateKey                           = Action("kms:CreateKey")
	Decrypt                             = Action("kms:Decrypt")
	DeleteAlias                         = Action("kms:DeleteAlias")
	DeleteCustomKeyStore                = Action("kms:DeleteCustomKeyStore")
	DeleteImportedKeyMaterial           = Action("kms:DeleteImportedKeyMaterial")
	DescribeCustomKeyStores             = Action("kms:DescribeCustomKeyStores")
	DescribeKey                         = Action("kms:DescribeKey")
	DisableKey                          = Action("kms:DisableKey")
	DisableKeyRotation                  = Action("kms:DisableKeyRotation")
	DisconnectCustomKeyStore            = Action("kms:DisconnectCustomKeyStore")
	EnableKey                           = Action("kms:EnableKey")
	EnableKeyRotation                   = Action("kms:EnableKeyRotation")
	Encrypt                             = Action("kms:Encrypt")
	GenerateDataKey                     = Action("kms:GenerateDataKey")
	GenerateDataKeyPair                 = Action("kms:GenerateDataKeyPair")
	GenerateDataKeyPairWithoutPlaintext = Action("kms:GenerateDataKeyPairWithoutPlaintext")
	GenerateDataKeyWithoutPlaintext     = Action("kms:GenerateDataKeyWithoutPlaintext")
	GenerateMac                         = Action("kms:GenerateMac")
	GenerateRandom                      = Action("kms:GenerateRandom")
	GetKeyPolicy                        = Action("kms:GetKeyPolicy")
	GetKeyRotationStatus                = Action("kms:GetKeyRotationStatus")
	GetParametersForImport              = Action("kms:GetParametersForImport")
	GetPublicKey                        = Action("kms:GetPublicKey")
	ImportKeyMaterial                   = Action("kms:ImportKeyMaterial")
	ListAliases                         = Action("kms:ListAliases")
	ListGrants                          = Action("kms:ListGrants")
	ListKeyPolicies                     = Action("kms:ListKeyPolicies")
	ListKeys                            = Action("kms:ListKeys")
	ListResourceTags                    = Action("kms:ListResourceTags")
	ListRetirableGrants                 = Action("kms:ListRetirableGrants")
	PutKeyPolicy                        = Action("kms:PutKeyPolicy")
	ReEncryptFrom                       = Action("kms:ReEncryptFrom")
	ReEncryptTo                         = Action("kms:ReEncryptTo")
	ReplicateKey                        = Action("kms:ReplicateKey")
	RetireGrant                         = Action("kms:RetireGrant")
	RevokeGrant                         = Action("kms:RevokeGrant")
	ScheduleKeyDeletion                 = Action("kms:ScheduleKeyDeletion")
	Sign                                = Action("kms:Sign")
	TagResource                         = Action("kms:TagResource")
	UntagResource                       = Action("kms:UntagResource")
	UpdateAlias                         = Action("kms:UpdateAlias")
	UpdateCustomKeyStore                = Action("kms:UpdateCustomKeyStore")
	UpdateKeyDescription                = Action("kms:UpdateKeyDescription")
	UpdatePrimaryRegion                 = Action("kms:UpdatePrimaryRegion")
	Verify                              = Action("kms:Verify")
	VerifyMac                           = Action("kms:VerifyMac")
	KmsAll                              = Action("kms:*")
)

然后我可以在代码中这样使用:

conn := kms.NewFromConfig(cfg)

policy := Policy{
	Version: "2012-10-17",
	ID:      "test-key",
	Statements: []*policy.Statement{
		{
			ID:            "test-failure",
			Effect:        policy.Allow,
			PrincipalArns: []string{"arn:aws:kms:eu-west-2:111122223333:root"},
			ActionArns:    policy.Actions{policy.KmsAll},
			ResourceArns:  []string{"*"},
		},
	},
}

pData, err := json.Marshal(policy)
if err != nil {
	return err
}

input := kms.CreateKeyInput{
	KeySpec:     types.KeySpecEccNistP521,
	KeyUsage:    types.KeyUsageTypeSignVerify,
	MultiRegion: aws.Bool(true),
	Policy:      aws.String(string(pData)),
}

output, err := conn.CreateKey(ctx, &input)

我将这段代码添加到了一个开源包中,可以在这里找到,以供他人使用。

英文:

I ended up creating my own policy structs:

// Policy describes a policy document that can be used to configure permissions in IAM
type Policy struct {
Version    string       `json:"Version"`
ID         string       `json:"Id"`
Statements []*Statement `json:"Statement"`
}
// Statement describes a set of permissions that define what resources and users should have access
// to the resources described therein
type Statement struct {
ID            string     `json:"Sid"`
Effect        Effect     `json:"Effect"`
PrincipalArns Principals `json:"Principal"`
ActionArns    Actions    `json:"Action"`
ResourceArns  Resources  `json:"Resource"`
}
// Principals describes a list of principals associated with a policy statement
type Principals []string
// MarhsalJSON converts a Principals collection to JSON
func (p Principals) MarshalJSON() ([]byte, error) {
// First, get the inner string from the list of principals
var inner string
if len(p) > 1 {
inner = marshal(p...)
} else if len(p) == 1 {
inner = strings.Quote(p[0], "\"")
} else {
return nil, fmt.Errorf("Principal must contain at least one element")
}
// Next, create the principal block and return it
return []byte(fmt.Sprintf("{\"AWS\": %s}", inner)), nil
}
// Actions describes a list of actions that may or may not be taken by principals with regard to the
// resources described in a policy statement
type Actions []Action
// MarshalJSON converts an Actions collection to JSON
func (a Actions) MarshalJSON() ([]byte, error) {
// First, get the inner string from the list of actions
var inner string
if len(a) > 1 {
inner = marshal(a...)
} else if len(a) == 1 {
inner = strings.Quote(a[0], "\"")
} else {
return nil, fmt.Errorf("Action must contain at least one element")
}
// Next, create the action block and return it
return []byte(inner), nil
}
// Resources describes a list of resources effected by the policy statement
type Resources []string
// MarshalJSON converts a Resources collection to JSON
func (r Resources) MarshalJSON() ([]byte, error) {
// First, get the inner string from the list of actions
var inner string
if len(r) > 1 {
inner = marshal(r...)
} else if len(r) == 1 {
inner = strings.Quote(r[0], "\"")
} else {
return nil, fmt.Errorf("Resource must contain at least one element")
}
// Next, create the action block and return it
return []byte(inner), nil
}
// Helper function that converts a list of items to a JSON-string
func marshal[S ~string](items ...S) string {
return "[" + strings.ModifyAndJoin(func(item string) string { return strings.Quote(item, "\"") }, ",", items...) + "]"
}
// Effect describes the effect a policy statement will have upon the resource and for the actions described
type Effect string
var (
// Allow to grant access of the resource and actions to the principals described in the policy statement
Allow = Effect("Allow")
// Deny to deny access of the resource and actions from the principals described in the policy statement
Deny = Effect("Deny")
)
// Action describes a valid operation that may be made against a particular AWS resource
type Action string
// Describes the various action types available to AWS
var (
CancelKeyDeletion                   = Action("kms:CancelKeyDeletion")
ConnectCustomKeyStore               = Action("kms:ConnectCustomKeyStore")
CreateAlias                         = Action("kms:CreateAlias")
CreateCustomKeyStore                = Action("kms:CreateCustomKeyStore")
CreateGrant                         = Action("kms:CreateGrant")
CreateKey                           = Action("kms:CreateKey")
Decrypt                             = Action("kms:Decrypt")
DeleteAlias                         = Action("kms:DeleteAlias")
DeleteCustomKeyStore                = Action("kms:DeleteCustomKeyStore")
DeleteImportedKeyMaterial           = Action("kms:DeleteImportedKeyMaterial")
DescribeCustomKeyStores             = Action("kms:DescribeCustomKeyStores")
DescribeKey                         = Action("kms:DescribeKey")
DisableKey                          = Action("kms:DisableKey")
DisableKeyRotation                  = Action("kms:DisableKeyRotation")
DisconnectCustomKeyStore            = Action("kms:DisconnectCustomKeyStore")
EnableKey                           = Action("kms:EnableKey")
EnableKeyRotation                   = Action("kms:EnableKeyRotation")
Encrypt                             = Action("kms:Encrypt")
GenerateDataKey                     = Action("kms:GenerateDataKey")
GenerateDataKeyPair                 = Action("kms:GenerateDataKeyPair")
GenerateDataKeyPairWithoutPlaintext = Action("kms:GenerateDataKeyPairWithoutPlaintext")
GenerateDataKeyWithoutPlaintext     = Action("kms:GenerateDataKeyWithoutPlaintext")
GenerateMac                         = Action("kms:GenerateMac")
GenerateRandom                      = Action("kms:GenerateRandom")
GetKeyPolicy                        = Action("kms:GetKeyPolicy")
GetKeyRotationStatus                = Action("kms:GetKeyRotationStatus")
GetParametersForImport              = Action("kms:GetParametersForImport")
GetPublicKey                        = Action("kms:GetPublicKey")
ImportKeyMaterial                   = Action("kms:ImportKeyMaterial")
ListAliases                         = Action("kms:ListAliases")
ListGrants                          = Action("kms:ListGrants")
ListKeyPolicies                     = Action("kms:ListKeyPolicies")
ListKeys                            = Action("kms:ListKeys")
ListResourceTags                    = Action("kms:ListResourceTags")
ListRetirableGrants                 = Action("kms:ListRetirableGrants")
PutKeyPolicy                        = Action("kms:PutKeyPolicy")
ReEncryptFrom                       = Action("kms:ReEncryptFrom")
ReEncryptTo                         = Action("kms:ReEncryptTo")
ReplicateKey                        = Action("kms:ReplicateKey")
RetireGrant                         = Action("kms:RetireGrant")
RevokeGrant                         = Action("kms:RevokeGrant")
ScheduleKeyDeletion                 = Action("kms:ScheduleKeyDeletion")
Sign                                = Action("kms:Sign")
TagResource                         = Action("kms:TagResource")
UntagResource                       = Action("kms:UntagResource")
UpdateAlias                         = Action("kms:UpdateAlias")
UpdateCustomKeyStore                = Action("kms:UpdateCustomKeyStore")
UpdateKeyDescription                = Action("kms:UpdateKeyDescription")
UpdatePrimaryRegion                 = Action("kms:UpdatePrimaryRegion")
Verify                              = Action("kms:Verify")
VerifyMac                           = Action("kms:VerifyMac")
KmsAll                              = Action("kms:*")
)

I can then use this in my code like so:

conn := kms.NewFromConfig(cfg)
policy := Policy {
Version: "2012-10-17",
ID:      "test-key",
Statements: []*policy.Statement{
{
ID:            "test-failure",
Effect:        policy.Allow,
PrincipalArns: []string{"arn:aws:kms:eu-west-2:111122223333:root"},
ActionArns:    policy.Actions{policy.KmsAll},
ResourceArns:  []string{"*"},
},
},
}
pData, err := json.Marshal(policy)
if err != nil {
return err
}
input := kms.CreateKeyInput{
KeySpec:     types.KeySpecEccNistP521,
KeyUsage:    types.KeyUsageTypeSignVerify,
MultiRegion: aws.Bool(true),
Policy:      aws.String(string(pData)),
}
output, err := conn.CreateKey(ctx, &input)

I added the code for this in an open-source package that can be found here so others can use it.

huangapple
  • 本文由 发表于 2022年10月4日 09:14:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/73942241.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定