mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
CLI: coder licenses list (#3686)
* Check GET license calls authz Signed-off-by: Spike Curtis <spike@coder.com> * CLI: coder licenses list Signed-off-by: Spike Curtis <spike@coder.com> Signed-off-by: Spike Curtis <spike@coder.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package coderd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/coderd/rbac"
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/coder/coder/testutil"
|
||||
)
|
||||
|
||||
// TestAuthorizeAllEndpoints will check `authorize` is called on every endpoint registered.
|
||||
// these tests patch the map of license keys, so cannot be run in parallel
|
||||
// nolint:paralleltest
|
||||
func TestAuthorizeAllEndpoints(t *testing.T) {
|
||||
pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
|
||||
require.NoError(t, err)
|
||||
keyID := "testing"
|
||||
oldKeys := keys
|
||||
defer func() {
|
||||
t.Log("restoring keys")
|
||||
keys = oldKeys
|
||||
}()
|
||||
keys = map[string]ed25519.PublicKey{keyID: pubKey}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
a := coderdtest.NewAuthTester(ctx, t, &coderdtest.Options{APIBuilder: NewEnterprise})
|
||||
|
||||
// We need a license in the DB, so that when we call GET api/v2/licenses there is one in the
|
||||
// list to check authz on.
|
||||
claims := &Claims{
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
Issuer: "test@coder.test",
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(2 * time.Hour)),
|
||||
},
|
||||
LicenseExpires: jwt.NewNumericDate(time.Now().Add(time.Hour)),
|
||||
AccountType: AccountTypeSalesforce,
|
||||
AccountID: "testing",
|
||||
Version: CurrentVersion,
|
||||
Features: Features{
|
||||
UserLimit: 0,
|
||||
AuditLog: 1,
|
||||
},
|
||||
}
|
||||
lic, err := makeLicense(claims, privKey, keyID)
|
||||
require.NoError(t, err)
|
||||
_, err = a.Client.AddLicense(ctx, codersdk.AddLicenseRequest{
|
||||
License: lic,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
skipRoutes, assertRoute := coderdtest.AGPLRoutes(a)
|
||||
assertRoute["POST:/api/v2/licenses"] = coderdtest.RouteCheck{
|
||||
AssertAction: rbac.ActionCreate,
|
||||
AssertObject: rbac.ResourceLicense,
|
||||
}
|
||||
assertRoute["GET:/api/v2/licenses"] = coderdtest.RouteCheck{
|
||||
StatusCode: http.StatusOK,
|
||||
AssertAction: rbac.ActionRead,
|
||||
AssertObject: rbac.ResourceLicense,
|
||||
}
|
||||
a.Test(ctx, assertRoute, skipRoutes)
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package coderd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/coderd/rbac"
|
||||
"github.com/coder/coder/enterprise/coderd"
|
||||
"github.com/coder/coder/testutil"
|
||||
)
|
||||
|
||||
// TestAuthorizeAllEndpoints will check `authorize` is called on every endpoint registered.
|
||||
func TestAuthorizeAllEndpoints(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
a := coderdtest.NewAuthTester(ctx, t, &coderdtest.Options{APIBuilder: coderd.NewEnterprise})
|
||||
skipRoutes, assertRoute := coderdtest.AGPLRoutes(a)
|
||||
assertRoute["POST:/api/v2/licenses"] = coderdtest.RouteCheck{
|
||||
AssertAction: rbac.ActionCreate,
|
||||
AssertObject: rbac.ResourceLicense,
|
||||
}
|
||||
// TODO: fix this test so that there are licenses to get.
|
||||
assertRoute["GET:/api/v2/licenses"] = coderdtest.RouteCheck{
|
||||
StatusCode: http.StatusOK,
|
||||
NoAuthorize: true,
|
||||
}
|
||||
a.Test(ctx, assertRoute, skipRoutes)
|
||||
}
|
||||
@@ -12,11 +12,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cdr.dev/slog"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"cdr.dev/slog"
|
||||
|
||||
"github.com/coder/coder/coderd"
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
@@ -253,7 +254,7 @@ func decodeClaims(l database.License) (jwt.MapClaims, error) {
|
||||
if len(parts) != 3 {
|
||||
return nil, xerrors.Errorf("Unable to parse license %d as JWT", l.ID)
|
||||
}
|
||||
cb, err := base64.URLEncoding.DecodeString(parts[1])
|
||||
cb, err := base64.RawURLEncoding.DecodeString(parts[1])
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("Unable to decode license %d claims: %w", l.ID, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user