Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
87 changes: 84 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: 1.22.x
go-version: 1.23.x
- name: Checkout code
uses: actions/checkout@v3
- name: Run linters
Expand All @@ -18,7 +18,7 @@ jobs:
go-test:
strategy:
matrix:
go-version: [1.22.x]
go-version: [1.23.x]
platform: [ubuntu-latest]
runs-on: ${{ matrix.platform }}
steps:
Expand All @@ -35,4 +35,85 @@ jobs:
if: always()
uses: guyarb/[email protected]
with:
test-results: test.json
test-results: test.json

test:
runs-on: ubuntu-latest
env:
BATON_LOG_LEVEL: debug
ONE_PASSWORD_EMAIL: ${{ secrets.EMAIL }}
ONE_PASSWORD_PASSWORD: ${{ secrets.PASSWORD }}
ONE_PASSWORD_SECRET_KEY: ${{ secrets.SECRET_KEY }}
ONE_PASSWORD_ACCOUNT_ADDRESS: ${{ secrets.ADDRESS }}
GROUP_ENTITLEMENT: ${{ vars.GROUP_ENTITLEMENT }}
GROUP_GRANT: ${{ vars.GROUP_GRANT }}
PRINCIPAL: ${{ vars.PRINCIPAL }}
VAULT_ENTITLEMENT: ${{ vars.VAULT_ENTITLEMENT }}
VAULT_GRANT: ${{ vars.VAULT_GRANT }}
PRINCIPAL_TYPE: ${{ vars.PRINCIPAL_TYPE }}

steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.23.x

- name: Checkout code
uses: actions/checkout@v4

- name: Install 1Password CLI
run: |
curl -sS https://downloads.1password.com/linux/keys/1password.asc | sudo gpg --dearmor -o /usr/share/keyrings/1password-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/1password-archive-keyring.gpg] https://downloads.1password.com/linux/debian/amd64 stable main' | sudo tee /etc/apt/sources.list.d/1password.list
sudo apt update
sudo apt install -y 1password-cli
op --version

- name: Build baton-1password
run: go build ./cmd/baton-1password

- name: Run baton-1password (generate sync.c1z)
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }}

- name: Install baton
run: |
chmod +x ./scripts/get-baton.sh
./scripts/get-baton.sh
mv baton /usr/local/bin/

- name: Grant entitlement Group
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }} --grant-entitlement=${{ env.GROUP_ENTITLEMENT }} --grant-principal=${{env.PRINCIPAL}} --grant-principal-type=${{ env.PRINCIPAL_TYPE }}

- name: Re-sync the data from 1password
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }}

- name: Check grants was granted
run: baton grants --entitlement="${{ env.GROUP_ENTITLEMENT }}" --output-format=json | jq --exit-status '.grants[].principal.id.resource == "${{ env.PRINCIPAL }}"' | grep true

- name: Revoke grants Group
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }} --revoke-grant="${{env.GROUP_GRANT}}"

- name: Re-sync the data from 1password
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }}

- name: Check grant was revoked
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }} && baton grants --entitlement="${{ env.GROUP_ENTITLEMENT }}" --output-format=json | jq --exit-status 'if .grants then .grants[]?.principal.id.resource != "${{ env.PRINCIPAL }}" else . end'

- name: Grant entitlement Vault
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }} --grant-entitlement=${{ env.VAULT_ENTITLEMENT }} --grant-principal=${{ env.PRINCIPAL }} --grant-principal-type=${{ env.PRINCIPAL_TYPE }}

- name: Re-sync the data from 1password
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }}

- name: Check grants was granted
run: baton grants --entitlement="${{ env.VAULT_ENTITLEMENT }}" --output-format=json | jq --exit-status '.grants[].principal.id.resource == "${{ env.PRINCIPAL }}"' | grep true

- name: Revoke grants Vault
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }} --revoke-grant="${{env.VAULT_GRANT}}"

- name: Re-sync the data from 1password
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }}

- name: Check grant was revoked
run: ./baton-1password --password=${{ env.ONE_PASSWORD_PASSWORD }} --email=${{ env.ONE_PASSWORD_EMAIL }} --secret-key=${{ env.ONE_PASSWORD_SECRET_KEY }} --address=${{ env.ONE_PASSWORD_ACCOUNT_ADDRESS }} && baton grants --entitlement="${{ env.VAULT_ENTITLEMENT }}" --output-format=json | jq --exit-status 'if .grants then .grants[]?.principal.id.resource != "${{ env.PRINCIPAL }}" else . end'

4 changes: 2 additions & 2 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: 1.22.x
go-version: 1.23.x
- name: Checkout code
uses: actions/checkout@v3
- name: Run linters
Expand All @@ -21,7 +21,7 @@ jobs:
go-test:
strategy:
matrix:
go-version: [ 1.22.x ]
go-version: [ 1.23.x ]
platform: [ ubuntu-latest ]
runs-on: ${{ matrix.platform }}
steps:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.22.x
go-version: 1.23.x
- name: Set up Gon
run: brew tap conductorone/gon && brew install conductorone/gon/gon
- name: Import Keychain Certs
Expand All @@ -43,7 +43,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.22.x
go-version: 1.23.x
- name: Docker Login
uses: docker/login-action@v1
with:
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@ Check out [Baton](https://github.com/conductorone/baton) to learn more about the
3. Installed 1Password [CLI Tool](https://developer.1password.com/docs/cli) on your local machine. For first time install please refer to the [Install](https://developer.1password.com/docs/cli/get-started/#install) chapter. It is not neccessary to do any other steps as the `baton-1password` will take care of creating an account and signing in.
If you already have the CLI tool installed but need to upgrade it to the latest version please refer to [this](https://developer.1password.com/docs/cli/upgrade/) article.

IMPORTANT NOTE: If a service account is used, its token must be stored in a local environment variable (OP_SERVICE_ACCOUNT_TOKEN) in order for the 1Password CLI to authenticate properly:
```
OP_SERVICE_ACCOUNT_TOKEN=your-service-account-token
```

## Connector capabilities

- The connector can be authenticated using either a regular user account or a 1Password service account.

- Sync Users, projects, groups and vaults.

- Supports Groups provision

- Support Vaults provision
IMPORTANT NOTE: Vault provisioning is limited with a service account:
When using a service account to run the connector, vault provisioning is limited by 1Password. Specifically, only vaults that were created by the same service account can be modified.
Vaults that were created by other users or service accounts cannot be granted or revoked permissions using a service account.

## brew

```
Expand Down
14 changes: 6 additions & 8 deletions pkg/connector/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,16 @@ func (g *groupResourceType) Grants(ctx context.Context, resource *v2.Resource, _
}

func (o *groupResourceType) Grant(ctx context.Context, principal *v2.Resource, entitlement *v2.Entitlement) (annotations.Annotations, error) {
l := ctxzap.Extract(ctx)

if principal.Id.ResourceType != resourceTypeUser.Id {
l.Warn(
"baton-1password: only users can be granted group membership",
zap.String("principal_type", principal.Id.ResourceType),
zap.String("principal_id", principal.Id.Resource),
)
return nil, fmt.Errorf("baton-1password: only users can be granted group membership")
}

err := o.cli.AddUserToGroup(ctx, entitlement.Resource.Id.Resource, entitlement.Slug, principal.Id.Resource)
role, err := extractRoleFromEntitlementID(entitlement.Id)
if err != nil {
return nil, fmt.Errorf("could not extract role: %w", err)
}

err = o.cli.AddUserToGroup(ctx, entitlement.Resource.Id.Resource, role, principal.Id.Resource)

if err != nil {
return nil, fmt.Errorf("baton-1password: failed adding user to group")
Expand Down
75 changes: 75 additions & 0 deletions pkg/connector/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package connector

import (
"fmt"
"strings"

v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
"github.com/conductorone/baton-sdk/pkg/annotations"
ent "github.com/conductorone/baton-sdk/pkg/types/entitlement"
mapset "github.com/deckarep/golang-set/v2"
)

// Populate entitlement options for a 1Password resource.
Expand All @@ -23,3 +25,76 @@ func annotationsForUserResourceType() annotations.Annotations {
annos.Update(&v2.SkipEntitlementsAndGrants{})
return annos
}

func extractRoleFromEntitlementID(entitlementID string) (string, error) {
parts := strings.Split(entitlementID, ":")
if len(parts) != 3 {
return "", fmt.Errorf("invalid entitlement ID: %s", entitlementID)
}
role := parts[2]
// Formatting to replace spaces with _
role = strings.ReplaceAll(role, " ", "_")
return role, nil
}

func uniqueStrings(input []string) []string {
set := mapset.NewSet[string]()
for _, s := range input {
set.Add(s)
}
return set.ToSlice()
}

func getPermissionsForGrantRevoke(permissionGrant string, accountType string, isRevoke bool) []string {
if isRevoke {
return getRevokePermissions(permissionGrant, accountType)
}
return getGrantPermissions(permissionGrant, accountType)
}

func getRevokePermissions(permissionGrant string, accountType string) []string {
switch permissionGrant {
case memberEntitlement:
if accountType == businessAccountType {
return uniqueStrings(append(
expandPermissionsForRevoke("view_items"),
"manage_vault",
))
}
return uniqueStrings(append(
expandPermissionsForRevoke("allow_viewing"),
"allow_managing",
))

case managerEntitlement:
if accountType == businessAccountType {
return []string{"manage_vault"}
}
return []string{"allow_managing"}

default:
return expandPermissionsForRevoke(permissionGrant)
}
}

func getGrantPermissions(permissionGrant string, accountType string) []string {
switch permissionGrant {
case memberEntitlement:
if accountType == businessAccountType {
return resolveDeps("view_items", reverseDependencyMap, make(map[string]bool))
}
return expandPermissions("allow_editing")

case managerEntitlement:
if accountType == businessAccountType {
return uniqueStrings(append(
expandPermissions("view_items"),
"manage_vault",
))
}
return expandPermissions("allow_managing")

default:
return expandPermissions(permissionGrant)
}
}
Loading
Loading