cloudflare-go icon indicating copy to clipboard operation
cloudflare-go copied to clipboard

v4: trying to create a user token: `These rules must pass for ... id must be present`

Open pmalek opened this issue 11 months ago • 2 comments

Confirmation

  • [x] My issue isn't already found on the issue tracker.
  • [x] I have replicated my issue using the latest version of the library and it is still present.

cloudflare-go version

v4.0.0

Go environment

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/USER/Library/Caches/go-build'
GOENV='/Users/USER/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/USER/.gvm/pkgsets/go1.23.4/global/pkg/mod'
GONOPROXY='github.com/Kong'
GONOSUMDB='github.com/Kong'
GOOS='darwin'
GOPATH='/Users/USER/.gvm/pkgsets/go1.23.4/global'
GOPRIVATE='github.com/Kong'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/USER/.gvm/gos/go1.23.4'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/USER/.gvm/gos/go1.23.4/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.23.4'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/USER/Library/Application Support/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/Users/USER/code_/own/bws-sync/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/0m/_63w01516tgf3cftmp9h7ylm0000gn/T/go-build3003870686=/tmp/go-build -gno-record-gcc-switches -fno-common'

Expected output

No error.

Actual output

2025/01/18 13:36:56 POST "https://api.cloudflare.com/client/v4/user/tokens": 400 Bad Request {"success":false,"errors":[{"code":400,"message":"- These rules must pass for `{ \"meta\": { \"key\": \"id\", \"value\": \"47xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" } }`\n  - id must be present"}],"messages":[],"result":null}

Code demonstrating the issue

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/caarlos0/env/v11"
	"github.com/cloudflare/cloudflare-go/v4"
	"github.com/cloudflare/cloudflare-go/v4/dns"
	"github.com/cloudflare/cloudflare-go/v4/option"
	"github.com/cloudflare/cloudflare-go/v4/shared"
	"github.com/cloudflare/cloudflare-go/v4/user"
	"github.com/cloudflare/cloudflare-go/v4/zones"
)

...

	api := cloudflare.NewClient(
		option.WithAPIToken(token),
	)

...

	token, err := api.User.Tokens.New(ctx, user.TokenNewParams{
		Name: cloudflare.String("test"),
		Policies: cloudflare.F([]shared.TokenPolicyParam{
			{
				Effect: cloudflare.F(shared.TokenPolicyEffectAllow),
				Resources: cloudflare.F(map[string]string{
					"com.cloudflare.Client.account.zone." + zoneID: "*",
				}),
				PermissionGroups: cloudflare.F([]shared.TokenPolicyPermissionGroupParam{
					{
						Meta: cloudflare.F(
							shared.TokenPolicyPermissionGroupsMetaParam{
								Key:   cloudflare.String("id"),
								Value: cloudflare.String("47xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), // REDACTED
							},
						),
					},
					{
						Meta: cloudflare.F(
							shared.TokenPolicyPermissionGroupsMetaParam{
								Key:   cloudflare.String("scopes"),
								Value: cloudflare.String("com.cloudflare.Client.account"),
							},
						),
					},
					{
						Meta: cloudflare.F(
							shared.TokenPolicyPermissionGroupsMetaParam{
								Key:   cloudflare.String("name"),
								Value: cloudflare.String("DNS Write"),
							},
						),
					},
				}),
			},
		}),
	})

Steps to reproduce

  1. Create API using v4 client.
  2. Try to create a user token

References

Old code using v0.114.0 of the API worked fine:

	token, err := api.CreateAPIToken(ctx, cloudflare.APIToken{
		Name: "test",
		Policies: []cloudflare.APITokenPolicies{
			{
				Effect: "allow",
				Resources: map[string]interface{}{
					"com.cloudflare.api.account.zone." + zoneID: "*",
				},
				PermissionGroups: []cloudflare.APITokenPermissionGroups{
					{
						ID:     "47xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
						Scopes: []string{"com.cloudflare.api.account"},
						Name:   "DNS Write",
					},
				},
			},
		},
	})

pmalek avatar Jan 18 '25 12:01 pmalek

I'm experiencing the same issue. It seems this is ultimately due to TokenPolicyParam's reference to PermissionGroups referencing the param.Field[[]TokenPolicyPermissionGroupParam] type. TokenPolicyPermissionGroupParam only references the Meta field. Yet, it seems there is a TokenPolicyPermissionGroup type, which includes the expected fields, such as ID, Meta, etc.

Would it be best to fix the type TokenPolicyPermissionGroupParam to reference multiple TokenPolicyPermissionGroup instances? It would be nice to see the documentation improvements regarding Permission Groups and their formatting with the updated V4 SDK. The Cloudflare Docs tutorial seems like it might be outdated.

nicholas-fedor avatar Feb 07 '25 18:02 nicholas-fedor

I have submitted a pull request after digging into this and coming up with a solution that enabled me to successfully generate tokens: https://github.com/cloudflare/cloudflare-go/pull/3906

nicholas-fedor avatar Feb 07 '25 20:02 nicholas-fedor

have you tried to use ID within the shared.TokenPolicyPermissionGroupParam struct? instead of just Meta?

jacobbednarz avatar Mar 31 '25 21:03 jacobbednarz

The method for creating a user token has been fixed and is currently working as intended. The example noted in the documentation works just fine now that the ID field is available. Reference: https://developers.cloudflare.com/api/go/resources/user/subresources/tokens/methods/create/ Note that while the generated example from the documentation references v3, it works just fine with the most recent version (v4).

This issue should be okay to close as resolved now.

nicholas-fedor avatar Apr 12 '25 01:04 nicholas-fedor

I can confirm that the example from the docs linked by @nicholas-fedor works.

For me it ended up being:

	token, err := client.User.Tokens.New(ctx, user.TokenNewParams{
		Name: cloudflare.F("test"),
		Policies: cloudflare.F([]shared.TokenPolicyParam{
			{
				Effect: cloudflare.F(shared.TokenPolicyEffectAllow),
				Resources: cloudflare.F(map[string]string{
					"com.cloudflare.api.account.zone." + zoneID: "*",
				}),
				PermissionGroups: cloudflare.F([]shared.TokenPolicyPermissionGroupParam{
					{
						ID: cloudflare.String("47xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
						Meta: cloudflare.F(
							shared.TokenPolicyPermissionGroupsMetaParam{
								Key:   cloudflare.String("name"),
								Value: cloudflare.String("DNS Write"),
							},
						),
					},

				}),
			},
		}),
	})

pmalek avatar Apr 12 '25 08:04 pmalek

This issue hasn't been updated in a while. If it's still reproducing, please comment to let us know. Thank you!

github-actions[bot] avatar Jun 11 '25 16:06 github-actions[bot]