/************************************************************************* * Copyright 2009-2015 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. * * This file may incorporate work covered under the following copyright * and permission notice: * * Software License Agreement (BSD License) * * Copyright (c) 2008, Regents of the University of California * All rights reserved. * * Redistribution and use of this software in source and binary forms, * with or without modification, are permitted provided that the * following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL, * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE, * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION, * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS. ************************************************************************/ package com.eucalyptus.auth.euare; import static com.eucalyptus.auth.euare.common.policy.IamPolicySpec.*; import java.security.KeyPair; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import javax.annotation.Nonnull; import javax.annotation.Nullable; import com.eucalyptus.auth.AuthContext; import com.eucalyptus.auth.AuthException; import com.eucalyptus.auth.AuthenticationLimitProvider; import com.eucalyptus.auth.Permissions; import com.eucalyptus.auth.PolicyEvaluationContext; import com.eucalyptus.auth.PolicyParseException; import com.eucalyptus.auth.ServerCertificate; import com.eucalyptus.auth.euare.policy.PolicyArnKey; import com.eucalyptus.auth.euare.principal.EuareAccessKey; import com.eucalyptus.auth.euare.principal.EuareAccount; import com.eucalyptus.auth.euare.principal.EuareCertificate; import com.eucalyptus.auth.euare.principal.EuareGroup; import com.eucalyptus.auth.euare.principal.EuareManagedPolicy; import com.eucalyptus.auth.euare.principal.EuareManagedPolicyVersion; import com.eucalyptus.auth.euare.principal.EuareOpenIdConnectProvider; import com.eucalyptus.auth.euare.principal.EuareRole; import com.eucalyptus.auth.euare.principal.EuareUser; import com.eucalyptus.auth.euare.principal.GlobalNamespace; import com.eucalyptus.auth.principal.AccessKey; import com.eucalyptus.auth.principal.AccountFullName; import com.eucalyptus.auth.principal.BaseInstanceProfile; import com.eucalyptus.auth.principal.BaseRole; import com.eucalyptus.auth.principal.Certificate; import com.eucalyptus.auth.euare.principal.EuareInstanceProfile; import com.eucalyptus.auth.principal.Policy; import com.eucalyptus.auth.principal.User; import com.eucalyptus.auth.util.Identifiers; import com.eucalyptus.auth.util.X509CertHelper; import com.eucalyptus.crypto.Certs; import com.eucalyptus.crypto.Crypto; import com.eucalyptus.crypto.util.B64; import com.eucalyptus.util.Exceptions; import com.eucalyptus.util.RestrictedTypes; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; class Privileged { public static EuareAccount createAccount( @Nonnull AuthContext requestUser, @Nullable String accountName, @Nullable String password, @Nullable String email ) throws AuthException { if ( !requestUser.isSystemUser( ) || !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ACCOUNT, "", (AccountFullName)null, IAM_CREATEACCOUNT, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( accountName != null ) { Accounts.reserveGlobalName( GlobalNamespace.Account_Alias, accountName ); } EuareAccount newAccount = Accounts.addAccount( accountName ); Map<String, String> info = null; if ( email != null ) { info = Maps.newHashMap( ); info.put( EuareUser.EMAIL, email ); } EuareUser admin = newAccount.addUser( User.ACCOUNT_ADMIN, "/", true/*enabled*/, info ); admin.resetToken(); if ( password != null ) { admin.setPassword( Crypto.generateEncryptedPassword( password ) ); admin.setPasswordExpires( System.currentTimeMillis( ) + AuthenticationLimitProvider.Values.getDefaultPasswordExpiry( ) ); } return newAccount; } public static void deleteAccount( AuthContext requestUser, EuareAccount account, boolean recursive ) throws AuthException { if ( !requestUser.isSystemUser() || !RestrictedTypes.filterPrivileged( ).apply( account ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } Accounts.deleteAccount( account.getName(), false/*forceDeleteSystem*/, recursive ); } public static boolean allowListOrReadAccountPolicy( AuthContext requestUser, EuareAccount account ) throws AuthException { return requestUser.isSystemUser() && RestrictedTypes.filterPrivileged( ).apply( account ) && Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_ACCOUNT, IAM_LISTACCOUNTPOLICIES ), account.getAccountNumber(), Accounts.getAccountFullName(account) ) && Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_ACCOUNT, IAM_GETACCOUNTPOLICY ), account.getAccountNumber(), Accounts.getAccountFullName(account) ); } public static void modifyAccount( AuthContext requestUser, EuareAccount account, String newName ) throws AuthException { if ( Accounts.isSystemAccount( account.getName( ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ACCOUNT, Accounts.getAccountFullName(account), account, IAM_CREATEACCOUNTALIAS, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } try { Accounts.reserveGlobalName( GlobalNamespace.Account_Alias, newName ); account.setName( newName ); } catch ( AuthException ae ) { if ( AuthException.INVALID_NAME.equals( ae.getMessage( ) ) ) { throw ae; } throw new AuthException( AuthException.CONFLICT ); } } public static void deleteAccountAlias( AuthContext requestUser, EuareAccount account, String alias ) throws AuthException { if ( Accounts.isSystemAccount( account ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ACCOUNT, Accounts.getAccountFullName(account), account, IAM_DELETEACCOUNTALIAS, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( Strings.isNullOrEmpty( alias ) ) { throw new AuthException( AuthException.EMPTY_ACCOUNT_NAME ); } // Only one alias is allowed by AWS IAM spec. Overwrite the current alias if matches. if ( alias.equals( account.getAccountAlias( ) ) ) { account.setNameUnsafe( account.getAccountNumber( ) ); } } public static List<String> listAccountAliases( AuthContext requestUser, EuareAccount account ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ACCOUNT, Accounts.getAccountFullName(account), account, IAM_LISTACCOUNTALIASES, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } List<String> aliases = Lists.newArrayList( ); if ( account.hasAccountAlias( ) ) { aliases.add( account.getAccountAlias( ) ); } return aliases; } public static EuareAccount getAccountSummary( AuthContext requestUser, EuareAccount account ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ACCOUNT, Accounts.getAccountFullName(account), account, IAM_GETACCOUNTSUMMARY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return account; } public static EuareGroup createGroup( AuthContext requestUser, EuareAccount account, String groupName, String path ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, "", account, IAM_CREATEGROUP, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.canAllocate( VENDOR_IAM, IAM_RESOURCE_GROUP, "", IAM_CREATEGROUP, requestUser, 1L ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return account.addGroup( groupName, path ); } public static boolean allowListGroup( AuthContext requestUser, EuareAccount account, EuareGroup group ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_GROUP, IAM_LISTGROUPS ), account.getAccountNumber( ), Accounts.getGroupFullName( group ) ); } public static boolean allowReadGroup( AuthContext requestUser, EuareAccount account, EuareGroup group ) throws AuthException { return Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_GETGROUP, requestUser ); } public static void deleteGroup( AuthContext requestUser, EuareAccount account, EuareGroup group, boolean recursive ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_DELETEGROUP, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.deleteGroup( group.getName( ), recursive ); } public static void modifyGroup( AuthContext requestUser, EuareAccount account, EuareGroup group, String newName, String newPath ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_UPDATEGROUP, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Strings.isNullOrEmpty( newName ) ) { group.setName( newName ); } if ( !Strings.isNullOrEmpty( newPath ) ) { group.setPath( newPath ); } } public static EuareUser createUser( AuthContext requestUser, EuareAccount account, String userName, String path ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, "", account, IAM_CREATEUSER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.canAllocate( VENDOR_IAM, IAM_RESOURCE_USER, "", IAM_CREATEUSER, requestUser, 1L ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return account.addUser( userName, path, true, null ); } public static boolean allowReadUser( AuthContext requestUser, EuareAccount account, User user ) throws AuthException { return Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_GETUSER, requestUser ); } public static boolean allowListUser( AuthContext requestUser, EuareAccount account, User user ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_USER, IAM_LISTUSERS ), account.getAccountNumber( ), Accounts.getUserFullName( user ) ); } public static void deleteUser( AuthContext requestUser, EuareAccount account, EuareUser user, boolean recursive ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_DELETEUSER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( user.isAccountAdmin( ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.deleteUser( user.getName( ), false/*forceDeleteAdmin*/, recursive ); } public static void modifyUser( AuthContext requestUser, EuareAccount account, EuareUser user, String newName, String newPath, Boolean enabled, Long passwordExpires, Map<String, String> info ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_UPDATEUSER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Strings.isNullOrEmpty( newName ) ) { // Not allowed to modify admin user if ( user.isAccountAdmin( ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } user.setName( newName ); } if ( !Strings.isNullOrEmpty( newPath ) ) { // Not allowed to modify admin user if ( user.isAccountAdmin( ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } user.setPath( newPath ); } if ( enabled != null ) { // Not allowed to disable system admin (admin@eucalyptus) user // Only system user can disable account admin if ( user.isSystemAdmin( ) && user.isAccountAdmin( ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } else if ( user.isAccountAdmin( ) && !requestUser.isSystemUser( ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } user.setEnabled( enabled ); } if ( passwordExpires != null ) { if ( passwordExpires > new Date( ).getTime( ) ) { user.setPasswordExpires( passwordExpires ); } } if ( info != null ) { user.setInfo( info ); } } public static void updateUserInfoItem( AuthContext requestUser, EuareAccount account, EuareUser user, String key, String value ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_UPDATEUSER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( value != null ) { user.setInfo( key, value ); } else { user.removeInfo( key ); } } public static void addUserToGroup( AuthContext requestUser, EuareAccount account, User user, EuareGroup group ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_ADDUSERTOGROUP, requestUser ) || !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_ADDUSERTOGROUP, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !group.hasUser( user.getName( ) ) ) { group.addUserByName( user.getName( ) ); } } public static void removeUserFromGroup( AuthContext requestUser, EuareAccount account, User user, EuareGroup group ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_REMOVEUSERFROMGROUP, requestUser ) || !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_REMOVEUSERFROMGROUP, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( group.hasUser( user.getName( ) ) ) { group.removeUserByName( user.getName( ) ); } } public static List<EuareGroup> listGroupsForUser( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_LISTGROUPSFORUSER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } List<EuareGroup> groups = Lists.newArrayList( ); for ( EuareGroup g : user.getGroups( ) ) { if ( !g.isUserGroup( ) ) { groups.add( g ); } } return groups; } public static EuareRole createRole( AuthContext requestUser, EuareAccount account, String roleName, String path, String assumeRolePolicy ) throws AuthException, PolicyParseException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, "", account, IAM_CREATEROLE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.canAllocate( VENDOR_IAM, IAM_RESOURCE_ROLE, "", IAM_CREATEROLE, requestUser, 1L ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return account.addRole( roleName, path, assumeRolePolicy ); } public static boolean allowListRole( AuthContext requestUser, EuareAccount account, BaseRole role ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_ROLE, IAM_LISTROLES ), account.getAccountNumber( ), Accounts.getRoleFullName( role ) ); } public static boolean allowReadRole( AuthContext requestUser, EuareAccount account, EuareRole role ) throws AuthException { return Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_GETROLE, requestUser ); } public static void deleteRole( AuthContext requestUser, EuareAccount account, EuareRole role ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_DELETEROLE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.deleteRole( role.getName( ) ); } public static void updateAssumeRolePolicy( AuthContext requestUser, EuareAccount account, EuareRole role, String assumeRolePolicy ) throws AuthException, PolicyParseException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_UPDATEASSUMEROLEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } role.setAssumeRolePolicy( assumeRolePolicy ); } public static EuareInstanceProfile createInstanceProfile( AuthContext requestUser, EuareAccount account, String instanceProfileName, String path ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_INSTANCE_PROFILE, "", account, IAM_CREATEINSTANCEPROFILE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.canAllocate( VENDOR_IAM, IAM_RESOURCE_INSTANCE_PROFILE, "", IAM_CREATEINSTANCEPROFILE, requestUser, 1L ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return account.addInstanceProfile( instanceProfileName, path ); } public static boolean allowListInstanceProfile( AuthContext requestUser, EuareAccount account, BaseInstanceProfile instanceProfile ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_INSTANCE_PROFILE, IAM_LISTINSTANCEPROFILES ), account.getAccountNumber( ), Accounts.getInstanceProfileFullName( instanceProfile ) ); } public static boolean allowReadInstanceProfile( AuthContext requestUser, EuareAccount account, EuareInstanceProfile instanceProfile ) throws AuthException { return Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_INSTANCE_PROFILE, Accounts.getInstanceProfileFullName( instanceProfile ), account, IAM_GETINSTANCEPROFILE, requestUser ); } public static void deleteInstanceProfile( AuthContext requestUser, EuareAccount account, EuareInstanceProfile instanceProfile ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_INSTANCE_PROFILE, Accounts.getInstanceProfileFullName( instanceProfile ), account, IAM_DELETEINSTANCEPROFILE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.deleteInstanceProfile( instanceProfile.getName( ) ); } public static void addRoleToInstanceProfile( AuthContext requestUser, EuareAccount account, EuareInstanceProfile instanceProfile, EuareRole role ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_INSTANCE_PROFILE, Accounts.getInstanceProfileFullName( instanceProfile ), account, IAM_ADDROLETOINSTANCEPROFILE, requestUser ) || !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_ADDROLETOINSTANCEPROFILE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } final EuareRole currentRole = instanceProfile.getRole(); if ( currentRole != null && currentRole.getName().equals( role.getName() ) ) { throw new AuthException( AuthException.CONFLICT ); } instanceProfile.setRole( role ); } public static void removeRoleFromInstanceProfile( AuthContext requestUser, EuareAccount account, EuareInstanceProfile instanceProfile, EuareRole role ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_INSTANCE_PROFILE, Accounts.getInstanceProfileFullName( instanceProfile ), account, IAM_REMOVEROLEFROMINSTANCEPROFILE, requestUser ) || !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_REMOVEROLEFROMINSTANCEPROFILE, requestUser )) { throw new AuthException( AuthException.ACCESS_DENIED ); } instanceProfile.setRole( null ); } public static List<EuareInstanceProfile> listInstanceProfilesForRole( AuthContext requestUser, EuareAccount account, EuareRole role ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_LISTINSTANCEPROFILESFORROLE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return (List<EuareInstanceProfile>)(List)role.getInstanceProfiles(); } public static boolean allowListInstanceProfileForRole( AuthContext requestUser, EuareAccount account, EuareInstanceProfile instanceProfile ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_INSTANCE_PROFILE, IAM_LISTINSTANCEPROFILESFORROLE ), account.getAccountNumber( ), Accounts.getInstanceProfileFullName( instanceProfile ) ); } public static boolean allowReadPolicy( AuthContext requestUser, EuareAccount account, EuareManagedPolicy policy ) throws AuthException { return Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), account, IAM_GETPOLICY, requestUser ); } public static boolean allowReadPolicyVersion( AuthContext requestUser, EuareAccount account, EuareManagedPolicy policy ) throws AuthException { return Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), account, IAM_GETPOLICYVERSION, requestUser ); } public static boolean allowListPolicy( AuthContext requestUser, EuareAccount account, EuareManagedPolicy policy ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_POLICY, IAM_LISTPOLICIES ), account.getAccountNumber( ), Accounts.getManagedPolicyFullName( policy ) ); } public static boolean allowListPolicyVersion( AuthContext requestUser, EuareAccount account, EuareManagedPolicy policy ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_POLICY, IAM_LISTPOLICYVERSIONS ), account.getAccountNumber( ), Accounts.getManagedPolicyFullName( policy ) ); } public static EuareManagedPolicy createManagedPolicy( final AuthContext requestUser, final EuareAccount account, final String name, final String path, final String description, final String policy ) throws AuthException, PolicyParseException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, "", account, IAM_CREATEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.canAllocate( VENDOR_IAM, IAM_RESOURCE_POLICY, "", IAM_CREATEPOLICY, requestUser, 1L ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return account.addPolicy( name, path, description, policy ); } public static void deletePolicy( final AuthContext requestUser, final EuareAccount account, final EuareManagedPolicy policy ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), account, IAM_DELETEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.deletePolicy( policy.getName( ) ); } public static EuareManagedPolicyVersion createManagedPolicyVersion( final AuthContext requestUser, final EuareAccount account, final EuareManagedPolicy managedPolicy, final String policy, final boolean setAsDefault ) throws AuthException, PolicyParseException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( managedPolicy ), account, IAM_CREATEPOLICYVERSION, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return managedPolicy.addPolicyVersion( policy, setAsDefault ); } public static void deleteManagedPolicyVersion( final AuthContext requestUser, final EuareAccount account, final EuareManagedPolicy managedPolicy, final Integer versionId ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( managedPolicy ), account, IAM_DELETEPOLICYVERSION, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } managedPolicy.deletePolicyVersion( versionId ); } public static void setDefaultPolicyVersion( final AuthContext requestUser, final EuareAccount account, final EuareManagedPolicy policy, final Integer versionId ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), account, IAM_SETDEFAULTPOLICYVERSION, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } policy.setPolicyVersion( versionId ); } private static void authWithPolicy( final EuareManagedPolicy policy, final Callable<Void> callable ) throws AuthException { try { PolicyEvaluationContext.builder( ) .attr( PolicyArnKey.CONTEXT_KEY, Accounts.getManagedPolicyArn( policy ) ) .build( ) .doWithContext( callable ); } catch ( final Exception e ) { Exceptions.findAndRethrow( e, AuthException.class ); throw Exceptions.toUndeclared( e ); } } public static void attachGroupPolicy( AuthContext requestUser, EuareAccount account, EuareGroup group, EuareManagedPolicy policy ) throws AuthException { authWithPolicy( policy, () -> { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_ATTACHGROUPPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_ATTACHGROUPPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( group.getAttachedPolicies( ).size( ) >= AuthenticationLimitProvider.Values.getPolicyAttachmentLimit( ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return null; } ); group.attachPolicy( policy ); } public static void attachRolePolicy( AuthContext requestUser, EuareAccount account, EuareRole role, EuareManagedPolicy policy ) throws AuthException { authWithPolicy( policy, () -> { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_ATTACHROLEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_ATTACHROLEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( role.getAttachedPolicies( ).size( ) >= AuthenticationLimitProvider.Values.getPolicyAttachmentLimit( ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return null; } ); role.attachPolicy( policy ); } public static void attachUserPolicy( AuthContext requestUser, EuareAccount account, EuareUser user, EuareManagedPolicy policy ) throws AuthException { if ( user.isAccountAdmin( ) ) { // policy attached to admin is reserved, could be used for account policy throw new AuthException( AuthException.ACCESS_DENIED ); } authWithPolicy( policy, () -> { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_ATTACHUSERPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_ATTACHUSERPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( user.getAttachedPolicies( ).size( ) >= AuthenticationLimitProvider.Values.getPolicyAttachmentLimit( ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return null; } ); user.attachPolicy( policy ); } public static void detachGroupPolicy( AuthContext requestUser, EuareAccount account, EuareGroup group, EuareManagedPolicy policy ) throws AuthException { authWithPolicy( policy, () -> { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_DETACHGROUPPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_DETACHGROUPPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return null; } ); group.detachPolicy( policy ); } public static void detachRolePolicy( AuthContext requestUser, EuareAccount account, EuareRole role, EuareManagedPolicy policy ) throws AuthException { authWithPolicy( policy, () -> { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_DETACHROLEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_DETACHROLEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return null; } ); role.detachPolicy( policy ); } public static void detachUserPolicy( AuthContext requestUser, EuareAccount account, EuareUser user, EuareManagedPolicy policy ) throws AuthException { authWithPolicy( policy, () -> { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_DETACHUSERPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_DETACHUSERPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return null; } ); user.detachPolicy( policy ); } public static List<EuareManagedPolicy> listGroupAttachedPolicies( AuthContext requestUser, EuareAccount account, EuareGroup group ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_LISTATTACHEDGROUPPOLICIES, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return group.getAttachedPolicies( ); } public static List<EuareManagedPolicy> listRoleAttachedPolicies( AuthContext requestUser, EuareAccount account, EuareRole role ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_LISTATTACHEDROLEPOLICIES, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return role.getAttachedPolicies( ); } public static List<EuareManagedPolicy> listUserAttachedPolicies( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_LISTATTACHEDUSERPOLICIES, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return user.getAttachedPolicies( ); } public static List<EuareGroup> listGroupsWithAttachedPolicy( AuthContext requestUser, EuareManagedPolicy policy ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_LISTENTITIESFORPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return policy.getGroups( ); } public static List<EuareRole> listRolesWithAttachedPolicy( AuthContext requestUser, EuareManagedPolicy policy ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_LISTENTITIESFORPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return policy.getRoles( ); } public static List<EuareUser> listUsersWithAttachedPolicy( AuthContext requestUser, EuareManagedPolicy policy ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_POLICY, Accounts.getManagedPolicyFullName( policy ), policy.getAccount( ), IAM_LISTENTITIESFORPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return policy.getUsers( ); } public static void putAccountPolicy( AuthContext requestUser, EuareAccount account, String name, String policy ) throws AuthException, PolicyParseException { if ( !requestUser.isSystemUser( ) || !RestrictedTypes.filterPrivileged( ).apply( account ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } // Can not add policy to system account "eucalyptus" if ( EuareAccount.SYSTEM_ACCOUNT.equals( account.getName( ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } EuareUser admin = account.lookupAdmin(); admin.putPolicy( name, policy ); } public static void putGroupPolicy( AuthContext requestUser, EuareAccount account, EuareGroup group, String name, String policy ) throws AuthException, PolicyParseException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_PUTGROUPPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } group.putPolicy( name, policy ); } public static void putUserPolicy( AuthContext requestUser, EuareAccount account, EuareUser user, String name, String policy ) throws AuthException, PolicyParseException { // Policy attached to account admin is the account policy. Only system admin can put policy to an account. if ( user.isAccountAdmin( ) || !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_PUTUSERPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } user.putPolicy( name, policy ); } public static void putRolePolicy( AuthContext requestUser, EuareAccount account, EuareRole role, String name, String policy ) throws AuthException, PolicyParseException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_PUTROLEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } role.putPolicy( name, policy ); } public static void deleteAccountPolicy( AuthContext requestUser, EuareAccount account, String name ) throws AuthException { if ( !requestUser.isSystemUser() || !RestrictedTypes.filterPrivileged( ).apply( account ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } EuareUser admin = account.lookupAdmin(); admin.removePolicy( name ); } public static void deleteGroupPolicy( AuthContext requestUser, EuareAccount account, EuareGroup group, String name ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_DELETEGROUPPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } group.removePolicy( name ); } public static void deleteUserPolicy( AuthContext requestUser, EuareAccount account, EuareUser user, String name ) throws AuthException { // Policy attached to account admin is the account policy. if ( user.isAccountAdmin( ) || !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_DELETEUSERPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } user.removePolicy( name ); } public static void deleteRolePolicy( AuthContext requestUser, EuareAccount account, EuareRole role, String name ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_DELETEROLEPOLICY, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } role.removePolicy( name ); } public static List<Policy> listAccountPolicies( AuthContext requestUser, EuareAccount account ) throws AuthException { if ( !allowListOrReadAccountPolicy( requestUser, account ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } EuareUser admin = account.lookupAdmin(); return admin.getPolicies( ); } public static List<Policy> listGroupPolicies( AuthContext requestUser, EuareAccount account, EuareGroup group ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_GROUP, Accounts.getGroupFullName( group ), account, IAM_LISTGROUPPOLICIES, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return group.getPolicies( ); } public static List<Policy> listUserPolicies( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { if ( !allowListUserPolicy( requestUser, account, user ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return user.getPolicies( ); } public static List<Policy> listRolePolicies( AuthContext requestUser, EuareAccount account, EuareRole role ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_LISTROLEPOLICIES, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return role.getPolicies( ); } public static Policy getAccountPolicy( AuthContext requestUser, EuareAccount account, String policyName ) throws AuthException { if ( !allowListOrReadAccountPolicy( requestUser, account ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( Strings.isNullOrEmpty( policyName ) ) { throw new AuthException( AuthException.EMPTY_POLICY_NAME ); } EuareUser admin = account.lookupAdmin(); Policy policy = null; for ( Policy p : admin.getPolicies( ) ) { if ( p.getName( ).equals( policyName ) ) { policy = p; break; } } return policy; } public static Policy getGroupPolicy( AuthContext requestUser, EuareAccount account, EuareGroup group, String policyName ) throws AuthException { if ( !allowReadGroupPolicy( requestUser, account, group ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( Strings.isNullOrEmpty( policyName ) ) { throw new AuthException( AuthException.EMPTY_POLICY_NAME ); } Policy policy = null; for ( Policy p : group.getPolicies( ) ) { if ( p.getName( ).equals( policyName ) ) { policy = p; break; } } return policy; } public static Policy getUserPolicy( AuthContext requestUser, EuareAccount account, EuareUser user, String policyName ) throws AuthException { if ( !allowReadUserPolicy( requestUser, account, user ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( Strings.isNullOrEmpty( policyName ) ) { throw new AuthException( AuthException.EMPTY_POLICY_NAME ); } Policy policy = null; for ( Policy p : user.getPolicies( ) ) { if ( p.getName( ).equals( policyName ) ) { policy = p; break; } } return policy; } public static Policy getRolePolicy( AuthContext requestUser, EuareAccount account, EuareRole role, String policyName ) throws AuthException { if ( !allowReadRolePolicy( requestUser, account, role ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( Strings.isNullOrEmpty( policyName ) ) { throw new AuthException( AuthException.EMPTY_POLICY_NAME ); } Policy policy = null; for ( Policy p : role.getPolicies( ) ) { if ( p.getName( ).equals( policyName ) ) { policy = p; break; } } return policy; } public static boolean allowReadGroupPolicy( AuthContext requestUser, EuareAccount account, EuareGroup group ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_GROUP, IAM_GETGROUPPOLICY ), account.getAccountNumber(), Accounts.getGroupFullName( group ) ); } public static boolean allowReadRolePolicy( AuthContext requestUser, EuareAccount account, EuareRole role ) throws AuthException { return Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_ROLE, Accounts.getRoleFullName( role ), account, IAM_GETROLEPOLICY, requestUser ); } public static boolean allowListUserPolicy( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { return !user.isAccountAdmin( ) && // we are not looking at account admin's policies and authorized Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_LISTUSERPOLICIES, requestUser ); } public static boolean allowReadUserPolicy( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { return !user.isAccountAdmin( ) && // we are not looking at account admin's policies and authorized Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_GETUSERPOLICY, requestUser ); } public static boolean allowListAccessKeys( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_USER, IAM_LISTACCESSKEYS ), account.getAccountNumber( ), Accounts.getUserFullName( user ) ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ; } public static boolean allowListSigningCertificates( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_USER, IAM_LISTSIGNINGCERTIFICATES ), account.getAccountNumber( ), Accounts.getUserFullName( user ) ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ; } public static AccessKey createAccessKey( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_CREATEACCESSKEY, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( user.getKeys( ).size( ) >= AuthenticationLimitProvider.Values.getAccessKeyLimit( ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return user.createKey( ); } public static void deleteAccessKey( AuthContext requestUser, EuareAccount account, EuareUser user, String keyId ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_DELETEACCESSKEY, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } user.removeKey( keyId ); } public static List<AccessKey> listAccessKeys( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { if ( !allowListAccessKeys( requestUser, account, user ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return user.getKeys(); } public static void modifyAccessKey( AuthContext requestUser, EuareAccount account, EuareUser user, String keyId, String status ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_UPDATEACCESSKEY, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( Strings.isNullOrEmpty( keyId ) ) { throw new AuthException( AuthException.EMPTY_KEY_ID ); } if ( Strings.isNullOrEmpty( status ) ) { throw new AuthException( AuthException.EMPTY_STATUS ); } final EuareAccessKey key = user.getKey( keyId ); key.setActive( "Active".equalsIgnoreCase( status ) ); } public static Certificate createSigningCertificate( AuthContext requestUser, EuareAccount account, EuareUser user, KeyPair keyPair ) throws AuthException { // Use the official UPLOADSIGNINGCERTIFICATE action here if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_UPLOADSIGNINGCERTIFICATE, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( user.getCertificates( ).size( ) >= AuthenticationLimitProvider.Values.getSigningCertificateLimit( ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } X509Certificate x509 = Certs.generateCertificate( keyPair, user.getName() ); String certificateId; try { x509.checkValidity( ); certificateId = Identifiers.generateCertificateIdentifier( x509 ); } catch ( Exception e ) { throw new AuthException( "Invalid X509 Certificate", e ); } Accounts.reserveGlobalName( GlobalNamespace.Signing_Certificate_Id, certificateId ); return user.addCertificate( certificateId, x509 ); } public static Certificate uploadSigningCertificate( AuthContext requestUser, EuareAccount account, EuareUser user, String certBody ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_UPLOADSIGNINGCERTIFICATE, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( user.getCertificates( ).size( ) >= AuthenticationLimitProvider.Values.getSigningCertificateLimit( ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } if ( Strings.isNullOrEmpty( certBody ) ) { throw new AuthException( AuthException.EMPTY_CERT ); } final String encodedPem = B64.url.encString( certBody ); final X509Certificate x509 = X509CertHelper.toCertificate( encodedPem ); if ( x509 == null ) { throw new AuthException( AuthException.INVALID_CERT ); } String certificateId; try { certificateId = Identifiers.generateCertificateIdentifier( x509 ); } catch ( CertificateEncodingException e ) { throw new AuthException( "Invalid X509 Certificate", e ); } Accounts.reserveGlobalName( GlobalNamespace.Signing_Certificate_Id, certificateId ); for ( Certificate c : user.getCertificates( ) ) { if ( c.getPem( ).equals( encodedPem ) ) { throw new AuthException( AuthException.CONFLICT ); } } return user.addCertificate( certificateId, x509 ); } public static List<Certificate> listSigningCertificates( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { if ( !allowListSigningCertificates( requestUser, account, user ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } List<Certificate> certs = Lists.newArrayList( ); for ( Certificate cert : user.getCertificates( ) ) { certs.add( cert ); } return certs; } public static void deleteSigningCertificate( AuthContext requestUser, EuareAccount account, EuareUser user, String certId ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_DELETESIGNINGCERTIFICATE, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } user.removeCertificate( certId ); } public static void modifySigningCertificate( AuthContext requestUser, EuareAccount account, EuareUser user, String certId, String status ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_UPDATESIGNINGCERTIFICATE, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( Strings.isNullOrEmpty( status ) ) { throw new AuthException( AuthException.EMPTY_STATUS ); } if ( Strings.isNullOrEmpty( certId ) ) { throw new AuthException( AuthException.EMPTY_CERT_ID ); } EuareCertificate cert = user.getCertificate( certId ); cert.setActive( "Active".equalsIgnoreCase( status ) ); } /** * Is the user allows to perform actions that should be restricted to the * account administrator or a system user with appropriate permissions. * * An authorization check is required in addition to this check. */ private static boolean accountAdminActionPermittedIfAuthorized( final AuthContext requestUser, final User user ) { return !user.isAccountAdmin( ) || requestUser.isAccountAdmin( ) || requestUser.isSystemUser( ); } public static void createLoginProfile( AuthContext requestUser, EuareAccount account, EuareUser user, String password ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_CREATELOGINPROFILE, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } setUserPassword( user, password ); } public static void deleteLoginProfile( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_DELETELOGINPROFILE, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } user.setPassword( null ); } public static boolean allowReadLoginProfile( AuthContext requestUser, EuareAccount account, EuareUser user ) throws AuthException { return Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_GETLOGINPROFILE, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ); } public static void updateLoginProfile( AuthContext requestUser, EuareAccount account, EuareUser user, String newPass ) throws AuthException { if ( !(Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_USER, Accounts.getUserFullName( user ), account, IAM_UPDATELOGINPROFILE, requestUser ) && accountAdminActionPermittedIfAuthorized( requestUser, user ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( null == user.getPassword( ) ) { throw new AuthException( AuthException.NO_SUCH_LOGIN_PROFILE ); } setUserPassword( user, newPass ); } private static void setUserPassword( EuareUser user, String newPass ) throws AuthException { if ( Strings.isNullOrEmpty( newPass ) || user.getName( ).equals( newPass ) || newPass.length( ) > EuareUser.MAX_PASSWORD_LENGTH ) { throw new AuthException( AuthException.INVALID_PASSWORD ); } String newEncrypted = Crypto.generateEncryptedPassword( newPass ); user.setPassword( newEncrypted ); user.setPasswordExpires( System.currentTimeMillis( ) + AuthenticationLimitProvider.Values.getDefaultPasswordExpiry( ) ); } public static void createServerCertificate( final AuthContext requestUser, final EuareAccount account, final String pemCertBody, final String pemCertChain, final String path, final String certName, final String pemPk ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_SERVER_CERTIFICATE, certName, account, IAM_UPLOADSERVERCERTIFICATE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.canAllocate( VENDOR_IAM, IAM_RESOURCE_SERVER_CERTIFICATE, "", IAM_UPLOADSERVERCERTIFICATE, requestUser, 1L ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } account.addServerCertificate(certName, pemCertBody, pemCertChain, path, pemPk); } public static List<ServerCertificate> listServerCertificate( final AuthContext requestUser, final EuareAccount account, final String pathPrefix ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_SERVER_CERTIFICATE, pathPrefix, account, IAM_LISTSERVERCERTIFICATES, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return account.listServerCertificates(pathPrefix); } public static ServerCertificate getServerCertificate( final AuthContext requestUser, final EuareAccount account, final String certName ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_SERVER_CERTIFICATE, certName, account, IAM_GETSERVERCERTIFICATE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } return account.lookupServerCertificate(certName); } public static void deleteServerCertificate( final AuthContext requestUser, final EuareAccount account, final String certName ) throws AuthException{ if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_SERVER_CERTIFICATE, certName, account, IAM_DELETESERVERCERTIFICATE, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.deleteServerCertificate(certName); } public static void updateServerCertificate( final AuthContext requestUser, final EuareAccount account, final String certName, final String newCertName, final String newPath ) throws AuthException { if ( ! ( Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_SERVER_CERTIFICATE, certName, account, IAM_UPDATESERVERCERTIFICATE, requestUser ) && Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_SERVER_CERTIFICATE, newCertName, account, IAM_UPDATESERVERCERTIFICATE, requestUser ) ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.updateServerCeritificate(certName, newCertName, newPath); } /* open id methods */ public static EuareOpenIdConnectProvider createOpenIdConnectProvider( AuthContext requestUser, EuareAccount account, String url, List<String> clientIDs, List<String> thumbprints ) throws AuthException, PolicyParseException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_OPENID_CONNECT_PROVIDER, "", account, IAM_CREATEOPENIDCONNECTPROVIDER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } if ( !Permissions.canAllocate( VENDOR_IAM, IAM_RESOURCE_OPENID_CONNECT_PROVIDER, "", IAM_CREATEOPENIDCONNECTPROVIDER, requestUser, 1L ) ) { throw new AuthException( AuthException.QUOTA_EXCEEDED ); } return account.createOpenIdConnectProvider( url, clientIDs, thumbprints ); } public static void deleteOpenIdConnectProvider( AuthContext requestUser, EuareAccount account, EuareOpenIdConnectProvider provider ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_OPENID_CONNECT_PROVIDER, provider.getUrl(), account, IAM_DELETEOPENIDCONNECTPROVIDER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.deleteOpenIdConnectProvider( provider.getUrl( ) ); } public static boolean allowListOpenIdConnectProviders( AuthContext requestUser, EuareAccount account, String url) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_OPENID_CONNECT_PROVIDER, IAM_LISTOPENIDCONNECTPROVIDERS ), account.getAccountNumber( ), url ); } public static boolean allowGetOpenIdConnectProvider( AuthContext requestUser, EuareAccount account, String url ) throws AuthException { return Permissions.isAuthorized( requestUser.evaluationContext( VENDOR_IAM, IAM_RESOURCE_OPENID_CONNECT_PROVIDER, IAM_GETOPENIDCONNECTPROVIDER ), account.getAccountNumber( ), url ); } public static void addClientIdToOpenIdConnectProvider( AuthContext requestUser, EuareAccount account, EuareOpenIdConnectProvider provider, String clientId ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_OPENID_CONNECT_PROVIDER, provider.getUrl(), account, IAM_ADDCLIENTIDTOOPENIDCONNECTPROVIDER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.addClientIdToOpenIdConnectProvider( clientId, provider.getUrl( ) ); } public static void removeClientIdFromOpenIdConnectProvider( AuthContext requestUser, EuareAccount account, EuareOpenIdConnectProvider provider, String clientId ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_OPENID_CONNECT_PROVIDER, provider.getUrl(), account, IAM_REMOVECLIENTIDFROMOPENIDCONNECTPROVIDER, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.removeClientIdFromOpenIdConnectProvider( clientId, provider.getUrl( ) ); } public static void updateOpenIdConnectProviderThumbprint( AuthContext requestUser, EuareAccount account, EuareOpenIdConnectProvider provider, List<String> thumbprints ) throws AuthException { if ( !Permissions.isAuthorized( VENDOR_IAM, IAM_RESOURCE_OPENID_CONNECT_PROVIDER, provider.getUrl(), account, IAM_UPDATEOPENIDCONNECTPROVIDERTHUMBPRINT, requestUser ) ) { throw new AuthException( AuthException.ACCESS_DENIED ); } account.updateOpenIdConnectProviderThumbprint( provider.getUrl( ), thumbprints ); } }