使用OpenStack4j身份服务(Keystone)V3


OpenStack4j是一个开源库,帮助您管理OpenStack部署。它是一个基于Fluent的API,可以让您完全控制各种OpenStack服务。

从中央网站获取Openstack4j的最新版本Maven repository。从3.0.0+版本开始,OpenStack4j现在可以选择底层连接框架。默认情况下,API配置为使用Jersey 2连接器。请参阅下面的可选配置方案:

默认设置(使用Jersey 2作为连接器)

<dependency>
    <groupId>org.pacesys</groupId>
    <artifactId>openstack4j</artifactId>
    <version>3.0.3</version>
</dependency>


使用依赖项(全部在一个JAR中)

<dependency>
    <groupId>org.pacesys</groupId>
    <artifactId>openstack4j</artifactId>
    <version>3.0.3</version>
    <classifier>withdeps</classifier>
</dependency>


使用您选择的连接器

  • 在POM中声明openstack4j核心依赖项

<dependency>
    <groupId>org.pacesys</groupId>
    <artifactId>openstack4j-core</artifactId>
    <version>3.0.3</version>
</dependency>
  • 声明连接器

<dependency>
    <groupId>org.pacesys.openstack4j.connectors</groupId>
    <artifactId>[ connector artifactId ]</artifactId>
    <version>3.0.3</version>
</dependency>


有效的artifactID为:openstack4j-jersey2,openstack4j-jersey2-jdk16[仅限OS4J 2.0.x],openstack4j-resteasy,openstack4j-okhttp和openStack4j-httpclient。

Identity Service V3

Identity(Keystone)V3服务提供了用户,组,区域,服务,端点,角色管理和授权的中央目录。这个API负责验证和提供对所有其他OpenStack服务的访问。API还允许管理员配置集中式访问策略,用户,域和项目。

版本3身份验证

import org.openstack4j.api.OSClient.OSClientV3;
import org.openstack4j.openstack.OSFactory;
import org.openstack4j.model.common.Identifier;

// use Identifier.byId("domainId") or Identifier.byName("example-domain")
Identifier domainIdentifier = Identifier.byId("domainId");

// unscoped authentication
// as the username is not unique across domains you need to provide the domainIdentifier
OSClientV3 os = OSFactory.builderV3()
                       .endpoint("http://127.0.0.1:5000/v3")
                       .credentials("admin","sample", domainIdentifier)
                       .authenticate();

// project scoped authentication
OSClientV3 os = OSFactory.builderV3()
                    .endpoint("http://127.0.0.1:5000/v3")
                    .credentials("admin", "secret", Identifier.byName("example-domain"))
                    .scopeToProject(Identifier.byId(projectIdentifier))
                    .authenticate();

// domain scoped authentication
// using the unique userId does not require a domainIdentifier
OSClientV3 os = OSFactory.builderV3()
                    .endpoint("http://127.0.0.1:5000/v3")
                    .credentials("userId", "secret")
                    .scopeToDomain(Identifier.byId(domainIdentifier))
                    .authenticate();

// Scoping to a project just by name isn't possible as the project name is only unique within a domain.
// You can either use this as the id of the project is unique across domains  
OSClientV3 os = OSFactory.builderV3()
                    .endpoint("http://127.0.0.1:5000/v3")
                    .credentials("userId", "secret")
                    .scopeToProject(Identifier.byName(projectName), Identifier.byName(domainName))
                    .authenticate();

// Or alternatively
OSClientV3 os = OSFactory.builderV3()
                    .endpoint("http://127.0.0.1:5000/v3")
                    .credentials("userId", "secret")
                    .scopeToDomain(Identifier.byName(domainName))
                    .authenticate();


区域

OpenStack4j支持在同一客户机内从一个区域切换到另一个区域的能力。如果您有区域部署(例如:西海岸和东海岸),并且希望将某些呼叫定位到特定区域,请参阅下面的示例:

切换到其他区域

// Switch to East Coast
os.useRegion("EastRegion");
List<? extends Server> eastServers = os.compute().servers().list();

// Switch to West Coast
os.useRegion("WestRegion");
List<? extends Server> westServers = os.compute().servers().list();

// Switch to Default - No region specified
os.removeRegion();


创建区域

Region region = os.identity().regions()
                                .create(Builders.regions()
                                .id("EastRegion")
                                .description("Region for east coast")
                                .build());


查询区域

查找所有区域

List<? extends Region> regionList = os.identity().regions().list();


查找特定区域

//Find by ID
Region region = os.identity().regions().get("EastRegion");


更新区域

此示例将通过查找并更新EastRegion,将EastRegion的描述从east coast的Region更改为east coast Region。该示例还展示了API的流畅性,以及您可以如何轻松地通过builder进入和退出可变状态

Region region = os.identity().regions().get("EastRegion");
if (region != null)
  region = os.identity().regions().update(region.toBuilder().description("East coast region").build());


正在删除区域

此示例将删除我们一直使用的EastRegion

os.identity().regions().delete(region.getId());


下面的示例将显示基本的域操作

正在创建域

Domain domain = os.identity().domains().create(Builders.domain()
            .name("domainName")
            .description("This is a new domain.")
            .enabled(true)
            .build());


正在查询域

查找所有域

List<? extends Domain> domainList = os.identity().domains().list();

查找特定域

//Find by ID
Domain domain = os.identity().domains().get("domainId");


正在更新域

此示例将通过查找域并更新它,将该域的enabled-status从true更改为false。该示例还展示了API的流畅性,以及您可以如何轻松地通过builder进入和退出可变状态

Domain domain = os.identity().domains().get("domainId");
if (domain != null)
  domain = os.identity().domains().update(domain.toBuilder().enabled(false).build());

删除域

此示例将删除我们一直使用的域

os.identity().domains().delete(domain.getId());

项目

下面的示例将显示基本的项目操作

创建项目

Project project = os.identity().projects().create(Builders.project()
            .name("projectName")
            .description("This is a new project.")
            .enabled(true)
            .build());


查询项目

查找所有项目

List<? extends Project> projectList = os.identity().projects().list();


查找特定项目

//Find by ID
Project project = os.identity().projects().get("projectId");
//Find by Name and Domain
Project project = os.identity().projects().getByName("projectName","projectDomainId");

//Find by Name accross all Domains
List<? extends Project> projectList = os.identity().projects().getByName("projectName");


更新项目

此示例将通过查找域并更新它,将项目的enabled-status从true更改为false。该示例还展示了API的流畅性,以及您可以如何轻松地通过builder进入和退出可变状态

Project project = os.identity().projects().get("projectId");
if (project != null)
  project = os.identity().projects().update(project.toBuilder().enabled(false).build());


删除项目

这个例子将删除我们一直在处理的项目

os.identity().projects().delete(project.getId());


用户

下面的示例将显示基本的用户操作

创建用户

User user = os.identity().users().create(Builders.user()
                                            .name("Foobar")
                                            .description("A new user.")
                                            .password("secret")
                                            .email("foobar@example.org")
                                            .domainId("domainId")
                                            .build());


查询用户

查找所有用户

List<? extends User> userList = os.identity().users().list();

查找特定用户

//Find by ID
User user = os.identity().users().get("userId");

//Find by name and domain
User user = os.identity().users().getByName("userName", "userDomainId");

// Find user by name across all domains
List<? extends Users> userList = os.identity().users().getByName("userName");


列出用户角色

//In a Domain
List<? extends Role> domainUserRolesList = os.identity().users().listDomainUserRoles("userId", "domainId");

//In a Project
List<? extends Role> projectUserRolesList = os.identity().users().listProjectUserRoles("userId", "projectId");


列出用户的组

List<? extends Group> userGroupsList = os.identity().users().listUserGroups("userId");


更新用户

本例将通过查找用户Foobar并进行更新,将用户Foobar的电子邮件从Foobar@example.org更改为Foobar@openstack.com。该示例还展示了API的流畅性,以及您可以如何轻松地通过builder进入和退出可变状态

User user = os.identity().users().get("userId");
if (user != null)
  user = os.identity().users().update(user.toBuilder().email("foobar@openstack.com").build());


删除用户

这个例子将删除我们一直使用的用户Foobar

os.identity().users().delete(user.getId());

下面的示例将显示基本的组操作

创建组

Group group = os.identity().groups().create(Builders.group()
                                                .name("myGroup")
                                                .description("A new group.")
                                                .domainId("domainId")
                                                .build());

查询组

查找所有组

List<? extends Group> groupList = os.identity().groups().list();


查找特定组

//Find by ID
Group group = os.identity().groups().get("groupId");

//Find by Name
List<? extends Group> groupList = os.identity().groups().getByName("groupName")


列出组中的用户

List<? extends User> userGroupList = os.identity().groups().listGroupUsers("groupId");


集团管理

// Add user to group
os.identity().groups().addUserToGroup("groupId", "userId");

// Check if a user is a member of a group
os.identity().groups().checkGroupUser("groupId", "userId");

// Remove user from group
os.identity().groups().removeUserFromGroup("groupId", "userId");


更新组

Group group = os.identity().groups().get("groupId");
if (group != null)
  group = os.identity().groups().update(group.toBuilder().description("admin-group").build());


删除组

此示例将删除我们一直使用的组myGroup

os.identity().groups().delete(group.getId());


角色管理

下面的示例将展示基本的角色和角色管理操作

创建角色

Role role = os.identity().roles().create(Builders.role()
                                            .name("developer")
                                            .build());


正在查询角色

查找所有角色

List<? extends Role> roleList = os.identity().roles().list();


查找特定角色

//Find by ID
Role role = os.identity().roles().get("roleId");

//Find by Name
List<? extends Role> roleList = os.identity().roles().getByName("roleName")


角色分配

此示例将展示如何在项目和域上下文中向用户和组授予角色和从用户和组撤销角色。

给用户

//Grant a role to a user in a project
ActionResponse grantProjectRole = os.identity().roles().grantProjectUserRole("projectId", "userId", "roleId");

//Check if a user has a specific role in a project
ActionResponse checkProjectRole = os.identity().roles().checkProjectUserRole("projectId", "userId", "roleId");

//Revoke a role from a user in a project
ActionResponse revokeProjectRole = os.identity().roles().revokeProjectUserRole("projectId", "userId", "roleId");

//Grant a role to a user in a domain
ActionResponse grantDomainRole = os.identity().roles().grantDomainUserRole("domainId", "userId", "roleId");

//Check if a user has a specific role in a domain
ActionResponse checkDomainRole = os.identity().roles().checkDomainUserRole("domainId", "userId", "roleId");

//Revoke a role from a user in a domain
ActionResponse revokeDomainRole = os.identity().roles().revokeDomainUserRole("domainId", "userId", "roleId");


给一个团体

//Grant a role to a group in a project
ActionResponse grantProjectRole = os.identity().roles().grantProjectGroupRole("projectId", "groupId", "roleId");

//Check if a group has a specific role in a project
ActionResponse checkProjectRole = os.identity().roles().checkProjectGroupRole("projectId", "groupId", "roleId");

//Revoke a role from a group in a project
ActionResponse revokeProjectRole = os.identity().roles().revokeProjectGroupRole("projectId", "groupId", "roleId");

//Grant a role to a group in a domain
ActionResponse grantDomainRole = os.identity().roles().grantDomainGroupRole("domainId", "groupId", "roleId");

//Check if a group has a specific role in a domain
ActionResponse checkDomainRole = os.identity().roles().checkDomainGroupRole("domainId", "groupId", "roleId");

//Revoke a role from a group in a domain
ActionResponse revokeDomainRole = os.identity().roles().revokeDomainGroupRole("domainId", "groupId", "roleId");


更新角色

此示例将通过查找角色并更新它,将角色的名称从developer更改为admin-role。该示例还展示了API的流畅性,以及您可以如何轻松地通过Builder进入和退出可变状态:

Role role = os.identity().roles().get("roleId");
if (role != null)
  role = os.identity().roles().update(role.toBuilder().name("admin-role").build());


删除角色

此示例将删除我们一直使用的角色

os.identity().roles().delete(role.getId());


政策

下面的示例将显示基本的策略操作

创建策略

Policy policy = os.identity().policies().create(Builders.policy()
                                                    .blob("{'foobar' : 'role:admin-user'}")
                                                    .type("application/json")
                                                    .projectId("projectId")
                                                    .userId("userId")
                                                    .build());


正在查询策略

查找所有策略

List<? extends Policy> policyList = os.identity().policies().list();


查找特定策略

//Find by ID
Policy policy_byId = os.identity().policies().get("policyId");


更新策略

此示例将通过查找策略并更新它,将策略的blob从{'foobar':'role:admin-user'}更改为{'foobar':'role:demo-user'}。该示例还展示了API的流畅性,以及您可以如何轻松地通过Builder进入和退出可变状态:

Policy policy = os.identity().policies().get("policyId");
if (policy != null)
  policy = os.identity().policies().update(policy.toBuilder().blob("{'foobar': 'role:demo-user'}").build());

删除策略

此示例将删除我们一直使用的策略

os.identity().policies().delete(policy.getId());

服务和终结点

下面的示例将显示基本的服务和端点操作

创建服务

Service service = os.identity().serviceEndpoints().create(Builders.service()
                                                            .type("serviceType")
                                                            .name("serviceName")
                                                            .description("A new service.")
                                                            .enabled(true)
                                                            .build());

正在查询服务

查找所有服务

List<? extends Service> serviceList = os.identity().serviceEndpoints().list();

查找特定服务

//Find by ID
Service service = os.identity().serviceEndpoints().get("serviceId");

更新服务

此示例将更改对服务的描述,从“一个新服务”。通过查找服务并更新它,来访问“Identity V3 service”。该示例还展示了API的流畅性,以及您可以通过Builder轻松地进入和退出可变状态。

Service service = os.identity().services().get("serviceId");
if (service != null)
  service = os.identity().services().update(service.toBuilder().description("Identity V3 Service").build());


删除服务

此示例将删除我们一直使用的服务

os.identity().services().delete(service.getId());


为服务创建终结点

此示例将为由其标识符指定的服务创建端点。

Endpoint endpoint = os.identity().serviceEndpoints().createEndpoint(Builders.endpoint()
                                                                        .name("endpointName")
                                                                        .url(new URL( "http", "devstack.openstack.stack", 5000, "/v3"))
                                                                        .iFace(Facing.ADMIN).regionId("regionId")
                                                                        .serviceId("serviceId")
                                                                        .enabled(true)
                                                                        .build());


正在查询终结点

查找所有可用端点

List<? extends Endpoint> endpointList = os.identity().serviceEndpoints().listEndpoints()


查找特定终结点

Endpoint endpoint = os.identity().serviceEndpoints().getEndpoint("endpointId")


正在更新终结点

此示例将通过查找端点并对其进行更新,将端点的URL从http://devstack.openstack.stack:5000/v3更改为http://openstack.stack:5000/v3。该示例还展示了API的流畅性,以及您可以通过Builder轻松地进入和退出可变状态。

Endpoint endpoint = os.identity().services().getEndpoint("endpointId");
if (endpoint != null)
  endpoint = os.identity().services().updateEndpoint(endpoint.toBuilder().url(new URL( "http", "openstack.stack", 5000, "/v3")).build());


正在删除终结点

os.identity().serviceEndpoints().deleteEndpoint("endpointId");


凭据

下面的示例将显示基本的凭据操作

创建凭据

Credential credential = os.identity().credentials().create(Builders.credential()
                                            .blob("{\"access\":\"181920\",\"secret\":\"secretKey\"}")
                                            .type("ec2")
                                            .projectId("projectId")
                                            .userId("userId")
                                            .build());


查找所有凭据

List<? extends Credential> credentialList = os.identity().credentials().list();


查找特定凭据

//Find by ID
Credential credential = os.identity().credentials().get("credentialId");

正在更新凭据

此示例将从以下位置更改凭据的BLOB:

{“Access”:“181920”,“Secret”:“SecretKey”}

{“Access”:“181920”,“Secret”:“UpdatedSecretKey”}

通过查找凭据并更新它。该示例还展示了API的流畅性,以及您可以如何轻松地通过builder进入和退出可变状态

Credential credential = os.identity().credentials().get("credential id");
if (credential != null)
    credential = os.identity().credentials().update(credential.toBuilder()
                                .blob("{\"access\":\"181920\",\"secret\":\"updatedSecretKey\"}")
                                .build());

删除凭据

此示例将删除我们一直使用的凭据

os.identity().credentials().delete("credentialId");

令牌

在身份验证期间获得令牌。请参阅认证指南。

正在验证另一个令牌

// validate and show details for another token
Token token = os.identity().tokens().get("USER_TOKEN_ID")

// validate another token
ActionResponse validateToken = os.identity().tokens().check("USER_TOKEN_ID")

获取另一个令牌的服务目录

// get service catalog for
List<? extends Service> serviceCatalog = os.identity().tokens().getServiceCatalog("USER_TOKEN_ID");

获取其他令牌的可用范围

// get available project scopes
List<? extends Project> availableProjectScopes = os.identity().tokens().getProjectScopes("USER_TOKEN_ID");

// get available domain scopes
List<? extends Domain> availableDomainScopes = os.identity().tokens().getDomainScopes("USER_TOKEN_ID");

正在删除另一个令牌

ActionResponse deleteToken = os.identity().tokens().delete("USER_TOKEN_ID")