Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge v3 into feature-http-proxy #1355

Merged
merged 65 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
eefd981
Add a noop rebac admin api server + GH auth to devenv
pkulik0 Jul 4, 2024
db97d34
Merge branch 'canonical:v3' into CSS-9387-add-rebac-admin-backend-server
pkulik0 Jul 4, 2024
0286dcc
Add test for rebac admin server
pkulik0 Jul 4, 2024
9e02193
PR comments + remove gh secrets thanks to repo visiblity change
pkulik0 Jul 16, 2024
57d20d5
Rename rebac pkg to rebac_admin, move backend setup to that pkg
pkulik0 Jul 18, 2024
b2d3ec6
Merge pull request #1262 from pkulik0/CSS-9387-add-rebac-admin-backen…
pkulik0 Jul 19, 2024
ddd14ae
CSS-9389 Implement the `EntitlementsService` interface (#1277)
SimoneDutto Jul 22, 2024
4d7fea5
Move `CofgaParamsToJIMMOpenFGAParams` to `jimmtest`, don't move servi…
pkulik0 Jul 23, 2024
3bffb8a
Change status code in rebac admin api test
pkulik0 Jul 23, 2024
1c71976
Sort imports in jimmtest auth.go
pkulik0 Jul 23, 2024
ae194e4
Revert changes to service.go & related, add some logging to rebac aut…
pkulik0 Jul 24, 2024
0ad483b
Change httptest recorder to a dummyWriter
pkulik0 Jul 24, 2024
6a30014
Reorganize imports
pkulik0 Jul 24, 2024
ce5300f
CSS-9834 groups skeleton (#1281)
kian99 Jul 25, 2024
df1cc23
Merge branch 'v3' into merge-v3-rebac
kian99 Jul 25, 2024
ff1ae01
Change rebac admin api auth approach to middleware
pkulik0 Jul 25, 2024
451e52e
Merge branch 'feature-rebac-admin' into CSS-9386-rebac-auth-interface
pkulik0 Jul 25, 2024
fdd2349
Merge pull request #1282 from kian99/merge-v3-rebac
kian99 Jul 25, 2024
85ac569
Merge branch 'feature-rebac-admin' into CSS-9386-rebac-auth-interface
pkulik0 Jul 26, 2024
bbd1c36
Change oauth authenticator mock args in test
pkulik0 Jul 26, 2024
48a63b0
CSS-9828 group pagination (#1284)
kian99 Jul 29, 2024
4e82025
Merge branch 'feature-rebac-admin' into CSS-9386-rebac-auth-interface
pkulik0 Jul 29, 2024
b0f06a9
Move auth middleware to a separate pkg
pkulik0 Jul 29, 2024
2c85222
Add more asserts in auth middleware test
pkulik0 Jul 29, 2024
95f29f8
CSS-9908: move relations methods from juju api to jimm package (#1280)
SimoneDutto Jul 29, 2024
6054007
Split auth middleware into two layers
pkulik0 Jul 29, 2024
e137f05
Rename rebac auth middleware test
pkulik0 Jul 29, 2024
975cf02
Merge branch 'feature-rebac-admin' into CSS-9386-rebac-auth-interface
babakks Jul 30, 2024
6451a48
Update go doc of AuthenticateBrowserSession of the mocked authenticator
pkulik0 Jul 30, 2024
6f54e8f
Merge pull request #1279 from pkulik0/CSS-9386-rebac-auth-interface
pkulik0 Jul 30, 2024
dfb1d6e
Upgrade to `[email protected]` (#1291)
babakks Jul 30, 2024
4166b03
Merge branch 'v3' into merge-v3
kian99 Aug 1, 2024
a05c83b
Merge pull request #1294 from kian99/merge-v3
kian99 Aug 1, 2024
658e785
Avoid use of auth client outside of jimm
kian99 Aug 1, 2024
f27392f
Merge pull request #1295 from kian99/avoid-openfga-client-access
kian99 Aug 2, 2024
e1301f2
Merge branch 'v3' into merge-v3
kian99 Aug 5, 2024
40be819
fix conflicts
kian99 Aug 5, 2024
fbfdd83
Merge pull request #1301 from kian99/merge-v3
kian99 Aug 5, 2024
3aea2c7
Css 9953/identity crudi (#1292)
SimoneDutto Aug 5, 2024
ca3516c
CSS-9827 group crud (#1296)
kian99 Aug 6, 2024
8677009
CSS-9829 group identities (#1303)
kian99 Aug 6, 2024
2941687
Merge branch 'v3' into merge-v3
kian99 Aug 8, 2024
d30e349
Merge pull request #1308 from kian99/merge-v3
kian99 Aug 8, 2024
9cadede
Css 9959/identity rels (#1305)
SimoneDutto Aug 9, 2024
713dbe5
Remove db from jujuapi (#1297)
kian99 Aug 15, 2024
c6c28c0
CSS-9830 Implement GetGroupEntitlements (#1315)
kian99 Aug 21, 2024
adb7aea
CSS-9830 patch group entitlements (#1318)
kian99 Aug 23, 2024
c51ea1d
Css 10074/ids entitlements (#1324)
SimoneDutto Aug 27, 2024
36f8f4b
Merge branch 'v3' into merge-v3-feature-rebac-admin
kian99 Sep 2, 2024
ff488d9
fix issues
kian99 Sep 2, 2024
f26f3a5
fix linting issues
kian99 Sep 2, 2024
cc0cf5a
ignore integer conversion linting errors
kian99 Sep 3, 2024
8b2e86f
fix test
kian99 Sep 3, 2024
8766152
Merge pull request #1339 from kian99/merge-v3-feature-rebac-admin
kian99 Sep 3, 2024
392c265
fixes for composite action (#1343)
kian99 Sep 3, 2024
7734e22
minor repo cleanup (#1340)
kian99 Sep 4, 2024
17bc480
Add CORS middleware (#1349)
kian99 Sep 4, 2024
f0c184b
Css 9402/resources (#1347)
SimoneDutto Sep 4, 2024
3ac2615
Merge branch 'v3' into merge-v3-feature-rebac-admin
kian99 Sep 4, 2024
5d2faa0
fix missing docstring
kian99 Sep 4, 2024
abc1aed
Merge pull request #1350 from kian99/merge-v3-feature-rebac-admin
kian99 Sep 4, 2024
c300fef
Cleanup model proxy (#1345)
kian99 Sep 4, 2024
9b24af6
Merge branch 'v3' into merge-v3-feature-rebac-admin
kian99 Sep 5, 2024
dbb1f38
Merge pull request #1352 from kian99/merge-v3-feature-rebac-admin
kian99 Sep 5, 2024
0ccb303
Merge pull request #1351 from canonical/feature-rebac-admin
kian99 Sep 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions .github/actions/test-server/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,21 @@ runs:
username: ${{ github.actor }}
password: ${{ inputs.ghcr-pat }}

# We can't use a make target here because a composite action
# doesn't have a .git folder when checked out.
- name: Start server based on released version
if: ${{ inputs.jimm-version != 'dev' }}
run: make integration-test-env
run: |
cd local/traefik/certs; ./certs.sh; cd - && \
docker compose --profile test up -d --wait
shell: bash
working-directory: ${{ github.action_path }}/../../..
env:
JIMM_VERSION: ${{ inputs.jimm-version }}

- name: Start server based on development version
if: ${{ inputs.jimm-version == 'dev' }}
working-directory: ${{ github.action_path }}/../../..
run: make dev-env
shell: bash

Expand All @@ -59,6 +65,7 @@ runs:
echo 'jimm-ca<<EOF' >> $GITHUB_OUTPUT
cat ./local/traefik/certs/ca.crt >> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT
working-directory: ${{ github.action_path }}/../../..
shell: bash

- name: Initialise LXD
Expand All @@ -73,6 +80,7 @@ runs:
- name: Setup cloud-init script for bootstraping Juju controllers
run: ./local/jimm/setup-controller.sh
shell: bash
working-directory: ${{ github.action_path }}/../../..
env:
SKIP_BOOTSTRAP: true
CLOUDINIT_FILE: "cloudinit.temp.yaml"
Expand All @@ -83,7 +91,7 @@ runs:
provider: "lxd"
channel: "5.19/stable"
juju-channel: ${{ inputs.juju-channel }}
bootstrap-options: "--config cloudinit.temp.yaml --config login-token-refresh-url=https://jimm.localhost/.well-known/jwks.json"
bootstrap-options: "--config ${{ github.action_path }}/../../../cloudinit.temp.yaml --config login-token-refresh-url=https://jimm.localhost/.well-known/jwks.json"

# As described in https://github.com/charmed-kubernetes/actions-operator grab the newly setup controller name
- name: Save LXD controller name
Expand All @@ -100,18 +108,21 @@ runs:

- name: Authenticate Juju CLI
run: chmod -R 666 ~/.local/share/juju/*.yaml && ./local/jimm/setup-cli-auth.sh
working-directory: ${{ github.action_path }}/../../..
shell: bash
# Below is a hardcoded JWT using the same test-secret used in JIMM's docker compose and allows the CLI to authenticate as the [email protected] user.
env:
JWT: ZXlKMGVYQWlPaUpLVjFRaUxDSmhiR2NpT2lKSVV6STFOaUo5LmV5SnBjM01pT2lKUGJteHBibVVnU2xkVUlFSjFhV3hrWlhJaUxDSnBZWFFpT2pFM01qUXlNamcyTmpBc0ltVjRjQ0k2TXprMk5EYzFNelEyTUN3aVlYVmtJam9pYW1sdGJTSXNJbk4xWWlJNkltcHBiVzB0ZEdWemRFQmpZVzV2Ym1sallXd3VZMjl0SW4wLkpTWVhXcGF6T0FnX1VFZ2hkbjlOZkVQdWxhWWlJQVdaX3BuSmRDbnJvWEk=

- name: Add LXD Juju controller to JIMM
run: ./local/jimm/add-controller.sh
working-directory: ${{ github.action_path }}/../../..
shell: bash
env:
JIMM_CONTROLLER_NAME: "jimm"
CONTROLLER_NAME: ${{ steps.lxd-controller.outputs.name }}

- name: Provide service account with cloud-credentials
run: ./local/jimm/setup-service-account.sh
working-directory: ${{ github.action_path }}/../../..
shell: bash
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ permissions:
jobs:
golangci:
name: Lint
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
8 changes: 3 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ simplify:
gofmt -w -l -s .

# Generate version information
version/commit.txt: FORCE
version/commit.txt:
git rev-parse --verify HEAD > version/commit.txt

version/version.txt: FORCE
version/version.txt:
if [ -z "$(GIT_VERSION)" ]; then \
echo "dev" > version/version.txt; \
else \
Expand Down Expand Up @@ -155,6 +155,4 @@ help:
@echo 'make rock - Build the JIMM rock.'
@echo 'make load-rock - Load the most recently built rock into your local docker daemon.'

.PHONY: build check install release clean format server simplify sys-deps help FORCE

FORCE:
.PHONY: build check install release clean format server simplify sys-deps help
9 changes: 9 additions & 0 deletions charms/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# JIMM Charms

Charms are a packaging tool for deploying application using Juju.
See more on charms [here](https://juju.is/charms-architecture).

JIMM has a machine charm and a Kubernetes charm for deploying the
application on different substrates. Currently the machine charm
is not maintained in favor of the K8s charm.

The machine charm has not yet been moved to a separate repo.

## K8S Charm
The K8S charm can be found [here](https://github.com/canonical/jimm-k8s-operator/).
8 changes: 7 additions & 1 deletion cmd/jimmctl/cmd/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ type listGroupsCommand struct {

store jujuclient.ClientStore
dialOpts *jujuapi.DialOpts

limit int
offset int
}

// Info implements the cmd.Command interface.
Expand All @@ -349,6 +352,8 @@ func (c *listGroupsCommand) SetFlags(f *gnuflag.FlagSet) {
"yaml": cmd.FormatYaml,
"json": cmd.FormatJson,
})
f.IntVar(&c.limit, "limit", 0, "The maximum number of groups to return")
f.IntVar(&c.offset, "offset", 0, "The offset to use when requesting groups")
}

// Run implements Command.Run.
Expand All @@ -364,7 +369,8 @@ func (c *listGroupsCommand) Run(ctxt *cmd.Context) error {
}

client := api.NewClient(apiCaller)
groups, err := client.ListGroups()
req := apiparams.ListGroupsRequest{Limit: c.limit, Offset: c.offset}
groups, err := client.ListGroups(&req)
if err != nil {
return errors.E(err)
}
Expand Down
22 changes: 22 additions & 0 deletions cmd/jimmctl/cmd/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (

"github.com/juju/cmd/v3/cmdtesting"
gc "gopkg.in/check.v1"
"gopkg.in/yaml.v3"

"github.com/canonical/jimm/v3/cmd/jimmctl/cmd"
"github.com/canonical/jimm/v3/internal/cmdtest"
"github.com/canonical/jimm/v3/internal/dbmodel"
"github.com/canonical/jimm/v3/internal/jimmtest"
"github.com/canonical/jimm/v3/pkg/api/params"
)

type groupSuite struct {
Expand Down Expand Up @@ -116,6 +118,26 @@ func (s *groupSuite) TestListGroupsSuperuser(c *gc.C) {
c.Assert(strings.Contains(output, "test-group2"), gc.Equals, true)
}

func (s *groupSuite) TestListGroupsLimitSuperuser(c *gc.C) {
// alice is superuser
bClient := jimmtest.NewUserSessionLogin(c, "alice")

for i := 0; i < 3; i++ {
_, err := s.JimmCmdSuite.JIMM.Database.AddGroup(context.TODO(), fmt.Sprint("test-group", i))
c.Assert(err, gc.IsNil)
}

ctx, err := cmdtesting.RunCommand(c, cmd.NewListGroupsCommandForTesting(s.ClientStore(), bClient), "test-group", "--limit", "1", "--offset", "1")
c.Assert(err, gc.IsNil)
output := cmdtesting.Stdout(ctx)
groups := []params.Group{}
err = yaml.Unmarshal([]byte(output), &groups)
c.Assert(err, gc.IsNil)
c.Assert(groups, gc.HasLen, 1)
c.Assert(groups[0].Name, gc.Equals, "test-group1")
c.Assert(groups[0].UUID, gc.Not(gc.Equals), "")
}

func (s *groupSuite) TestListGroups(c *gc.C) {
// bob is not superuser
bClient := jimmtest.NewUserSessionLogin(c, "bob")
Expand Down
6 changes: 3 additions & 3 deletions cmd/jimmctl/cmd/relation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func (s *relationSuite) TestRemoveRelationViaFileSuperuser(c *gc.C) {
func (s *relationSuite) TestRemoveRelation(c *gc.C) {
// bob is not superuser
bClient := jimmtest.NewUserSessionLogin(c, "bob")
_, err := cmdtesting.RunCommand(c, cmd.NewRemoveRelationCommandForTesting(s.ClientStore(), bClient), "test-group1#member", "member", "test-group2")
_, err := cmdtesting.RunCommand(c, cmd.NewRemoveRelationCommandForTesting(s.ClientStore(), bClient), "group-testGroup1#member", "member", "group-testGroup2")
c.Assert(err, gc.ErrorMatches, `unauthorized \(unauthorized access\)`)
}

Expand Down Expand Up @@ -440,9 +440,9 @@ func (s *relationSuite) TestListRelationsWithError(c *gc.C) {

ctx := context.Background()
group := &dbmodel.GroupEntry{Name: "group-1"}
err = s.JIMM.DB().GetGroup(ctx, group)
err = s.JIMM.Database.GetGroup(ctx, group)
c.Assert(err, gc.IsNil)
err = s.JIMM.DB().RemoveGroup(ctx, group)
err = s.JIMM.Database.RemoveGroup(ctx, group)
c.Assert(err, gc.IsNil)

expectedData := apiparams.ListRelationshipTuplesResponse{
Expand Down
19 changes: 11 additions & 8 deletions cmd/jimmsrv/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ func start(ctx context.Context, s *service.Service) error {
return errors.E("jimm session store secret must be at least 64 characters")
}

corsAllowedOrigins := strings.Split(os.Getenv("CORS_ALLOWED_ORIGINS"), " ")

jimmsvc, err := jimmsvc.NewService(ctx, jimmsvc.Params{
ControllerUUID: os.Getenv("JIMM_UUID"),
DSN: os.Getenv("JIMM_DSN"),
Expand All @@ -167,17 +169,18 @@ func start(ctx context.Context, s *service.Service) error {
JWTExpiryDuration: jwtExpiryDuration,
InsecureSecretStorage: insecureSecretStorage,
OAuthAuthenticatorParams: jimmsvc.OAuthAuthenticatorParams{
IssuerURL: issuerURL,
ClientID: clientID,
ClientSecret: clientSecret,
Scopes: scopesParsed,
SessionTokenExpiry: sessionTokenExpiryDuration,
SessionCookieMaxAge: sessionCookieMaxAgeInt,
JWTSessionKey: sessionSecretKey,
IssuerURL: issuerURL,
ClientID: clientID,
ClientSecret: clientSecret,
Scopes: scopesParsed,
SessionTokenExpiry: sessionTokenExpiryDuration,
SessionCookieMaxAge: sessionCookieMaxAgeInt,
JWTSessionKey: sessionSecretKey,
SecureSessionCookies: secureSessionCookies,
},
DashboardFinalRedirectURL: os.Getenv("JIMM_DASHBOARD_FINAL_REDIRECT_URL"),
SecureSessionCookies: secureSessionCookies,
CookieSessionKey: []byte(sessionSecretKey),
CorsAllowedOrigins: corsAllowedOrigins,
})
if err != nil {
return err
Expand Down
32 changes: 27 additions & 5 deletions cmd/jimmsrv/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/juju/names/v5"
"github.com/juju/zaputil/zapctx"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/rs/cors"
"go.uber.org/zap"
"gorm.io/driver/postgres"
"gorm.io/gorm"
Expand All @@ -37,9 +38,11 @@ import (
"github.com/canonical/jimm/v3/internal/jujuapi"
"github.com/canonical/jimm/v3/internal/jujuclient"
"github.com/canonical/jimm/v3/internal/logger"
"github.com/canonical/jimm/v3/internal/middleware"
"github.com/canonical/jimm/v3/internal/openfga"
ofganames "github.com/canonical/jimm/v3/internal/openfga/names"
"github.com/canonical/jimm/v3/internal/pubsub"
"github.com/canonical/jimm/v3/internal/rebac_admin"
"github.com/canonical/jimm/v3/internal/vault"
"github.com/canonical/jimm/v3/internal/wellknownapi"
)
Expand Down Expand Up @@ -82,6 +85,10 @@ type OAuthAuthenticatorParams struct {
// SessionCookieMaxAge holds the max age for session cookies in seconds.
SessionCookieMaxAge int

// SecureSessionCookies determines if HTTPS must be enabled in order for JIMM
// to set cookies when creating browser based sessions.
SecureSessionCookies bool

// JWTSessionKey holds the secret key used for signing/verifying JWT tokens.
// See internal/auth/oauth2.go AuthenticationService.SessionSecretkey for more details.
JWTSessionKey string
Expand Down Expand Up @@ -175,14 +182,14 @@ type Params struct {
// the /callback in an authorisation code OAuth2.0 flow to finish the flow.
DashboardFinalRedirectURL string

// SecureSessionCookies determines if HTTPS must be enabled in order for JIMM
// to set cookies when creating browser based sessions.
SecureSessionCookies bool

// CookieSessionKey is a randomly generated secret passed via config used for signing
// cookie data. The recommended length is 32/64 characters from the Gorilla securecookie lib.
// https://github.com/gorilla/securecookie/blob/main/securecookie.go#L124
CookieSessionKey []byte

// CorsAllowedOrigins represents all addresses that are valid for cross-origin
// requests. A wildcard '*' is accepted to allow all cross-origin requests.
CorsAllowedOrigins []string
}

// A Service is the implementation of a JIMM server.
Expand Down Expand Up @@ -347,6 +354,7 @@ func NewService(ctx context.Context, p Params) (*Service, error) {
SessionTokenExpiry: p.OAuthAuthenticatorParams.SessionTokenExpiry,
SessionCookieMaxAge: p.OAuthAuthenticatorParams.SessionCookieMaxAge,
JWTSessionKey: p.OAuthAuthenticatorParams.JWTSessionKey,
SecureCookies: p.OAuthAuthenticatorParams.SecureSessionCookies,
Store: &s.jimm.Database,
SessionStore: sessionStore,
RedirectURL: redirectUrl,
Expand Down Expand Up @@ -380,13 +388,28 @@ func NewService(ctx context.Context, p Params) (*Service, error) {
return nil, errors.E(op, err, "failed to parse final redirect url for the dashboard")
}

rebacBackend, err := rebac_admin.SetupBackend(ctx, &s.jimm)
if err != nil {
return nil, errors.E(op, err)
}

// Setup CORS middleware
corsOpts := cors.New(cors.Options{
AllowedOrigins: p.CorsAllowedOrigins,
AllowedMethods: []string{"GET"},
AllowCredentials: true,
})
s.mux.Use(corsOpts.Handler)

// Setup all HTTP handlers.
mountHandler := func(path string, h jimmhttp.JIMMHttpHandler) {
s.mux.Mount(path, h.Routes())
}

s.mux.Mount("/metrics", promhttp.Handler())

s.mux.Mount("/rebac", middleware.AuthenticateRebac(rebacBackend.Handler(""), &s.jimm))

mountHandler(
"/debug",
debugapi.NewDebugHandler(
Expand All @@ -406,7 +429,6 @@ func NewService(ctx context.Context, p Params) (*Service, error) {
oauthHandler, err := jimmhttp.NewOAuthHandler(jimmhttp.OAuthHandlerParams{
Authenticator: authSvc,
DashboardFinalRedirectURL: p.DashboardFinalRedirectURL,
SecureCookies: p.SecureSessionCookies,
})
if err != nil {
zapctx.Error(ctx, "failed to setup authentication handler", zap.Error(err))
Expand Down
Loading
Loading