Skip to content
Open
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
93 changes: 93 additions & 0 deletions gms/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Groups Management Service (gms)

The ***gms*** service provides RESTful web service interface for group management operations. It handles creation, modification, deletion, and querying of user groups, as well as managing group memberships and permissions.

This service works with a user service that provides user identity information. TBD

## deployment
The `gms` war file can be renamed at deployment time in order to support an alternate service name, including
introducing additional path elements.
See <a href="https://github.com/opencadc/docker-base/tree/master/cadc-tomcat">cadc-tomcat</a> (war-rename.conf).

## configuration
The following runtime configuration must be made available via the `/config` directory.

### catalina.properties
This file contains java system properties to configure the tomcat server and some of the java libraries
used in the service.

See <a href="https://github.com/opencadc/docker-base/tree/master/cadc-tomcat">cadc-tomcat</a> for
system properties related to the deployment environment.

See <a href="https://github.com/opencadc/core/tree/master/cadc-util">cadc-util</a> for common system properties.

### cadc-registry.properties

See <a href="https://github.com/opencadc/reg/tree/master/cadc-registry">cadc-registry</a>.

### gms.properties
TBD. At minimum, the following properties are required:
- Corresponding user service base URL and the name of the user identity attribute.

## API Overview

The GMS service provides the following operations:

### Group Management
- **List all groups** - GET /groups
- **Create group** - PUT /groups
- **Get group** - GET /groups/{groupName}
- **Delete group** - DELETE /groups/{groupName}
- **Modify group** - POST /groups/{groupName}
- **Add/Remove user members** - POST/DELETE /groups/{groupName}/userMembers
- **Add/Remove group members** - POST/DELETE /groups/{groupName}/groupMembers/{groupName2} (Is it required to distinguish between user and group members?)

### Group Searching
- **Search by role** - GET /search?id={userID}&idType={idType}&role={role}
- **Search specific membership** - GET /search?group={groupIVOID} (repeatable; see OpenAPI)

### Authentication Methods
The service supports multiple authentication methods:
- **Client certificates** (CC) over HTTPS - `/groups/*` endpoints
- **Anonymous** (AN) access for listing operations

## Group Structure

Groups have the following key components:
- **Owner** - Can modify administrator/member lists and delete the group
- **Administrators** - Can modify administrator and member lists
- **Members** - Are granted access to resources the group is associated with

Both users and other groups can be members or administrators of a group.

## building it
```
gradle clean build
docker build -t gms -f Dockerfile .
```

## running it
```
docker run --rm --user tomcat:tomcat --volume=/path/to/external/config:/config:ro --name gms gms:latest
```

## testing it

### Unit tests
```
gradle clean test
```

### Integration tests
```
gradle clean intTest
```

For local testing against a running instance:
```
~/bin/int-test-localhost.sh
```

## API Documentation

For detailed API specifications including request/response formats, authentication requirements, and error codes, see the OpenAPI specification or the service capabilities endpoint at `/capabilities`.
65 changes: 65 additions & 0 deletions gms/model.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
@startuml GMS Domain Model

class Group {
- uri: URI
- description: String
- gid: Integer
- lastModified: Date
- owner: User
- userMembers: Set<User>
- userAdmins: Set<User>
- groupMembers: Set<Group>
- groupAdmins: Set<Group>
}

class User {
- identity: Identity
- firstName: String
- lastName: String
- email: String
}

class Identity {
- type: String
- value: String
}

enum IdentityType {
X500
OPENID
NUMERIC
}

enum Role {
OWNER
ADMIN
MEMBER
}

' Relationships
Group "1" *-- "1" User : owner
Group "1" o-- "0..*" User : userMembers
Group "1" o-- "0..*" User : userAdmins
Group "1" o-- "0..*" Group : groupMembers
Group "1" o-- "0..*" Group : groupAdmins

User "1" *-- "1" Identity : key identity

Identity ..> IdentityType : <<uses>>
Group ..> Role : <<defines>>

note right of Group
A group can contain both
users and other groups as
members or administrators
end note

note left of User
Users are identified by
a configurable identity
(primary key) that the
corresponding user service
provides
end note

@enduml
59 changes: 59 additions & 0 deletions gms/src/main/webapp/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## GMS OpenAPI root: path items under ./openapi/; shared parameters/schemas in ./openapi/components.yaml; standard HTTP error fragments in ./openapi/vosi/vosi-std-responses.yaml (avoid `$ref` from fragments back into this file — that can deadlock libopenapi/vacuum).
openapi: 3.1.0
info:
title: CANFAR Group Management System (GMS) API
description: |
This API provides RESTful access to group management operations in the CANFAR Group Management System.

Groups have an owner, a list of administrators, and a list of members. The list of members and
administrators can be composed of groups and users.

**Roles:**
- **owner** - Can modify administrators list and members list. Can delete the group.
- **admin** - Can modify the administrators and members list.
- **member** - Are granted access to the resources the group is associated with.

**Authentication Methods:**
- **CC** - Client certificates over HTTPS
- **JWT** - JWT Bearer token over HTTPS
- **AN** - Anonymous over HTTP

**User Identity:**
Users are identified by their unique userID in the Identity Provider (CANFAR HTTP username).
version: 1.0.0
contact:
url: https://www.canfar.net
tags:
Comment thread
andamian marked this conversation as resolved.
- name: Group Management
description: Operations for managing groups
- name: GMS
description: Operations for searching groups by user role (IVOA GMS 1.0)
- name: Group Membership
description: GMS membership and identity-related queries
- name: VOSI Capabilities
description: VOSI capability and probe operations
- name: Service availability
description: Service availability
- name: POSIX Groups
description: POSIX group id (gid) and group name mapping
servers:
Comment thread
andamian marked this conversation as resolved.
- url: /gms

paths:
/capabilities:
$ref: ./openapi/vosi/vosi-capabilities.yaml
/availability:
$ref: ./openapi/cadcvosi/availability.yaml
/groups:
$ref: ./openapi/service/group.yaml#/GroupsCollection
/groups/{groupName}:
$ref: ./openapi/service/group.yaml#/GroupById
/groups/{groupName}/userMembers/{userID}:
$ref: ./openapi/service/group.yaml#/GroupUserMembers
/groups/{groupName}/groupMembers/{groupName2}:
$ref: ./openapi/service/group.yaml#/GroupGroupMembers
/search:
$ref: ./openapi/gms/gms-search.yaml
/gidmap:
$ref: ./openapi/pm/posix-groupmap.yaml

31 changes: 31 additions & 0 deletions gms/src/main/webapp/openapi/cadcvosi/availability.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
get:
operationId: read-availability
Comment thread
andamian marked this conversation as resolved.
tags:
- Service availability
summary: Returns the availability status of the service
description: Get the set of descriptions for this service.
responses:
'200':
description: Service is available
content:
application/xml:
schema:
type: object
xml:
name: availability
properties:
available:
type: boolean
example: true
xml:
name: availability
prefix: vosi
namespace: http://www.ivoa.net/xml/VOSIAvailability/v1.0
note:
type: string
example: service is accepting requests
example:
available: true
note: service is accepting requests
'503':
$ref: ../vosi/vosi-std-responses.yaml#/service-unavailable
88 changes: 88 additions & 0 deletions gms/src/main/webapp/openapi/components.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Shared components for the GMS OpenAPI description (referenced from path fragments and the root document).
components:
parameters:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parameter definition style:

I found one of:

- name: groupID
  in: path
...

or (eg)

- $ref: {defined elsewhere}

to be the most compact. See VOSI.git for examples of params defined in separate files.

Having

groupID:
  name: groupID
...

is either redundant or confusing when the two values differ.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works in service parameters but not in components. In components the first occurrence is a key and the second one is the name. Although appears to be a repetition, that is not necessarily so as we could use a different value such as groupIDKey for example. Would that make the intention more obvious?

groupName:
name: groupName
in: path
required: true
description: |
The group name (simple identifier), e.g. teamA, myGroup
schema:
type: string
example: teamA
userID:
Comment thread
andamian marked this conversation as resolved.
name: userID
in: path
required: true
description: The unique user identifier (CANFAR HTTP username)
schema:
type: string
example: user1
idType:
name: idType
in: query
description: The type of userID (http, x509, cadc)
required: true
schema:
type: string
enum:
- http
- x509
- cadc
example: http

schemas:
Group:
type: object
Comment thread
andamian marked this conversation as resolved.
description: Representation of a group
User:
type: string
description: User identifier (CANFAR HTTP username)
example: "exampleuser"

examples:
example-group:
summary: Example group document (JSON/XML body shape)
value:
uri: "ivo://cadc.nrc.ca/gms#teamA"
owner: "owner1"
description: "Research team access group"
lastModified: "2015-07-24T17:38:18.000"
userMembers:
- "member1"
- "member2"
- "member3"
userAdmins:
- "admin1"
- "admin2"
groupMembers:
- uri: "ivo://cadc.nrc.ca/gms#shared-data"
- uri: "ivo://cadc.nrc.ca/gms#pipeline-users"
groupAdmins:
- uri: "ivo://cadc.nrc.ca/gms#platform-admins"

GroupXmlDetailed:
summary: Detailed group example (XML)
value: |
<group>
<uri>ivo://cadc.nrc.ca/gms#teamA</uri>
<owner>owner1</owner>
<description>Research team access group</description>
<lastModified>2015-07-24T17:38:18.000</lastModified>
<userMembers>
<user>member1</user>
<user>member2</user>
<user>member3</user>
</userMembers>
<userAdmins>
<user>admin1</user>
<user>admin2</user>
</userAdmins>
<groupMembers>
<group><uri>ivo://cadc.nrc.ca/gms#shared-data</uri></group>
<group><uri>ivo://cadc.nrc.ca/gms#pipeline-users</uri></group>
</groupMembers>
<groupAdmins>
<group><uri>ivo://cadc.nrc.ca/gms#platform-admins</uri></group>
</groupAdmins>
</group>
Loading
Loading