Skip to content
Draft
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
75 changes: 75 additions & 0 deletions net/secureservice/admission.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package secureservice

import "context"

const (
DefaultAdmissionIdentityClaim = "anytype_identity"
DefaultAdmissionNetworkClaim = "network_id"
DefaultAdmissionSubjectClaim = "sub"
DefaultAdmissionClockSkewSec = 60
)

type AdmissionConfig struct {
Enabled bool `yaml:"enabled"`
Required bool `yaml:"required"`
Issuer string `yaml:"issuer"`
Audience string `yaml:"audience"`
JWKSURL string `yaml:"jwksUrl"`
RequiredClaims map[string]any `yaml:"requiredClaims"`
IdentityClaim string `yaml:"identityClaim"`
NetworkClaim string `yaml:"networkClaim"`
SubjectClaim string `yaml:"subjectClaim"`
ClockSkewSec int `yaml:"clockSkewSec"`
}

func (c AdmissionConfig) WithDefaults() AdmissionConfig {
if c.IdentityClaim == "" {
c.IdentityClaim = DefaultAdmissionIdentityClaim
}
if c.NetworkClaim == "" {
c.NetworkClaim = DefaultAdmissionNetworkClaim
}
if c.SubjectClaim == "" {
c.SubjectClaim = DefaultAdmissionSubjectClaim
}
if c.ClockSkewSec == 0 {
c.ClockSkewSec = DefaultAdmissionClockSkewSec
}
return c
}

type AdmissionRequest struct {
Token string
Identity []byte
NetworkID string
PeerID string
ClientVersion string
}

type AdmissionClaims struct {
Subject string
Issuer string
Audience []string
NetworkID string
Identity []byte
Claims map[string]any
}

type AdmissionDecision struct {
Allowed bool
Reason string
Claims AdmissionClaims
}

type AdmissionVerifier interface {
VerifyAdmission(ctx context.Context, req AdmissionRequest) (AdmissionDecision, error)
}

type NoopAdmissionVerifier struct{}

func (NoopAdmissionVerifier) VerifyAdmission(ctx context.Context, req AdmissionRequest) (AdmissionDecision, error) {
return AdmissionDecision{
Allowed: true,
Reason: "admission disabled",
}, nil
}
56 changes: 56 additions & 0 deletions net/secureservice/admission_checker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package secureservice

import (
"context"

"github.com/anyproto/any-sync/net/secureservice/handshake"
"github.com/anyproto/any-sync/net/secureservice/handshake/handshakeproto"
)

func withAdmissionVerifier(ctx context.Context, checker handshake.CredentialChecker, verifier AdmissionVerifier, required bool, networkID string) handshake.CredentialChecker {
if verifier == nil {
return checker
}
if ctx == nil {
ctx = context.Background()
}
return admissionVerifierCredentialChecker{
CredentialChecker: checker,
ctx: ctx,
verifier: verifier,
required: required,
networkID: networkID,
}
}

type admissionVerifierCredentialChecker struct {
handshake.CredentialChecker
ctx context.Context
verifier AdmissionVerifier
required bool
networkID string
}

func (a admissionVerifierCredentialChecker) CheckCredential(remotePeerId string, cred *handshakeproto.Credentials) (handshake.Result, error) {
res, err := a.CredentialChecker.CheckCredential(remotePeerId, cred)
if err != nil {
return handshake.Result{}, err
}
if res.AdmissionToken == "" {
if a.required {
return handshake.Result{}, handshake.ErrInvalidCredentials
}
return res, nil
}
decision, err := a.verifier.VerifyAdmission(a.ctx, AdmissionRequest{
Token: res.AdmissionToken,
Identity: res.Identity,
NetworkID: a.networkID,
PeerID: remotePeerId,
ClientVersion: res.ClientVersion,
})
if err != nil || !decision.Allowed {
return handshake.Result{}, handshake.ErrInvalidCredentials
}
return res, nil
}
Loading
Loading