public PutMetricDataResponseType putMetricData(PutMetricDataType request) throws CloudWatchException { PutMetricDataResponseType reply = request.getReply(); final Context ctx = Contexts.lookup(); try { LOG.trace("put metric data called"); // IAM Action Check checkActionPermission(PolicySpec.CLOUDWATCH_PUTMETRICDATA, ctx); final OwnerFullName ownerFullName = ctx.getUserFullName(); final List<MetricDatum> metricData = validateMetricData(request.getMetricData()); final String namespace = validateNamespace(request.getNamespace(), true); final Boolean isUserAccountAdmin = Principals.isSameUser( Principals.systemUser(), Wrappers.unwrap(Context.class, Contexts.lookup()).getUser()); LOG.trace("Namespace=" + namespace); LOG.trace("metricData=" + metricData); MetricType metricType = getMetricTypeFromNamespace(namespace); if (metricType == MetricType.System && !isUserAccountAdmin) { throw new InvalidParameterValueException( "The value AWS/ for parameter Namespace is invalid."); } MetricDataQueue.getInstance() .insertMetricData(ownerFullName.getAccountNumber(), namespace, metricData, metricType); } catch (Exception ex) { handleException(ex); } return reply; }
public BaseMessage setUser(User user) { if (user == null) { this.setUser(Principals.nobodyUser()); } else { this.userId = user.getName(); this.effectiveUserId = user.isSystemAdmin() ? Principals.systemUser().getName() : user.getName(); } return this; }
/** * Just checks the basic S3 groups for membership of the userId. Caller must ensure that the * userId is a valid ID in the system. That is outside the scope of this method. * * @param userId * @param group * @return */ public static boolean isUserMember(String userId, ObjectStorageProperties.S3_GROUP group) { if (group == null) { return false; } if (ObjectStorageProperties.S3_GROUP.ALL_USERS_GROUP.equals(group)) { return true; } if (ObjectStorageProperties.S3_GROUP.AUTHENTICATED_USERS_GROUP.equals(group) && !Strings.isNullOrEmpty(userId) && !userId.equals(Principals.nobodyUser().getUserId())) { return true; } boolean isSystemAdmin = false; try { isSystemAdmin = (Principals.systemUser().getUserId().equals(userId) || Accounts.lookupSystemAdmin().getUserId().equals(userId)); } catch (AuthException e) { // Fall through LOG.debug( "Got auth exception trying to lookup system admin user for group membership check in ec2-bundle-read", e); } boolean isAWSExecReadUser = false; try { isAWSExecReadUser = Accounts.lookupAwsExecReadAdmin(false).getUserId().equals(userId); } catch (AuthException e) { // Fall through LOG.debug( "Got auth exception trying to lookup aws-exec-read admin user for group membership check in ec2-bundle-read", e); } if (ObjectStorageProperties.S3_GROUP.AWS_EXEC_READ.equals(group) && isAWSExecReadUser) { return true; } // System only (or euca/admin) in the ec2-bundle-read group if (ObjectStorageProperties.S3_GROUP.EC2_BUNDLE_READ.equals(group) && isSystemAdmin) { return true; } // System or euca/admin only in logging if (ObjectStorageProperties.S3_GROUP.LOGGING_GROUP.equals(group) && isSystemAdmin) { return true; } return false; }
public <TYPE extends BaseMessage> TYPE regarding(BaseMessage msg, String subCorrelationId) { String corrId = null; if (msg == null) { this.correlationId = UUID.randomUUID().toString(); } else { corrId = msg.correlationId; } if (subCorrelationId == null) { subCorrelationId = String.format("%f", Math.random()).substring(2); } this.userId = Principals.systemFullName().getUserName(); this.effectiveUserId = Principals.systemFullName().getUserName(); this.correlationId = corrId + "-" + subCorrelationId; return (TYPE) this; }
public void update(final Cluster cluster, final List<ClusterAddressInfo> ccList) { Helper.loadStoredAddresses(); for (final ClusterAddressInfo addrInfo : ccList) { try { final Address address = Helper.lookupOrCreate(cluster, addrInfo); if (address.isAssigned() && !addrInfo.hasMapping() && !address.isPending()) { if (Principals.nobodyFullName().equals(address.getOwner())) { Helper.markAsAllocated(cluster, addrInfo, address); } try { final VmInstance vm = VmInstances.lookupByPrivateIp(addrInfo.getInstanceIp()); clearOrphan(addrInfo); } catch (final NoSuchElementException e) { try { final VmInstance vm = VmInstances.lookup(address.getInstanceId()); clearOrphan(addrInfo); } catch (final NoSuchElementException ex) { InetAddress addr = null; try { addr = Inet4Address.getByName(addrInfo.getInstanceIp()); } catch (final UnknownHostException e1) { LOG.debug(e1, e1); } if ((addr == null) || !addr.isLoopbackAddress()) { handleOrphan(cluster, addrInfo); } } } } else if (address.isAllocated() && Principals.nobodyFullName().equals(address.getOwner()) && !address.isPending()) { Helper.markAsAllocated(cluster, addrInfo, address); } } catch (final Exception e) { LOG.debug(e, e); } } }
public void init() { // Should only EVER be called externally after loading from the db this.atomicState = new AtomicMarkableReference<State>(State.unallocated, false); this.transition = this.QUIESCENT; this.getOwner(); // ensure to initialize if (this.instanceAddress == null || this.instanceId == null) { this.instanceAddress = UNASSIGNED_INSTANCEADDR; this.instanceUuid = UNASSIGNED_INSTANCEUUID; this.instanceId = UNASSIGNED_INSTANCEID; } if (Principals.nobodyFullName().equals(super.getOwner())) { this.atomicState.set(State.unallocated, true); this.instanceAddress = UNASSIGNED_INSTANCEADDR; this.instanceUuid = UNASSIGNED_INSTANCEUUID; this.instanceId = UNASSIGNED_INSTANCEID; Addresses.getInstance().registerDisabled(this); this.atomicState.set(State.unallocated, false); } else if (!this.instanceId.equals(UNASSIGNED_INSTANCEID)) { this.atomicState.set(State.assigned, true); Addresses.getInstance().register(this); this.atomicState.set(State.assigned, false); } else { this.atomicState.set(State.allocated, true); if (this.isSystemOwned()) { Addresses.getInstance().registerDisabled(this); this.setOwner(Principals.nobodyFullName()); this.instanceAddress = UNASSIGNED_INSTANCEADDR; this.instanceUuid = UNASSIGNED_INSTANCEUUID; this.instanceId = UNASSIGNED_INSTANCEID; Address.removeAddress(this.getDisplayName()); this.atomicState.set(State.unallocated, false); } else { Addresses.getInstance().register(this); this.atomicState.set(State.allocated, false); } } LOG.debug("Initialized address: " + this.toString()); }
private void fireUsageEvent( final OwnerFullName ownerFullName, final Supplier<EventActionInfo<AddressAction>> actionInfoSupplier) { if (!Principals.isFakeIdentityAccountNumber(ownerFullName.getAccountNumber())) { try { ListenerRegistry.getInstance() .fireEvent( AddressEvent.with( getNaturalId(), getDisplayName(), ownerFullName, Accounts.lookupAccountById(ownerFullName.getAccountNumber()).getName(), actionInfoSupplier.get())); } catch (final Exception e) { LOG.error(e, e); } } }
/* * Simply determines if the userId is a member of the groupId, very simplistic only for ALL_USERS and AUTHENTICATED_USERS, not arbitrary groups. * Arbitrary groups are not yet supported in Walrus bucket policies/IAM policies. */ public static boolean isUserMember(String userId, String groupId) { if (groupId == null) { return false; } if (groupId.equals(WalrusProperties.ALL_USERS_GROUP)) { return true; } if (groupId.equals(WalrusProperties.AUTHENTICATED_USERS_GROUP) && userId != null && !"".equals(userId) && !userId.equals(Principals.nobodyUser().getUserId())) { return true; } return false; }
@SuppressWarnings("unchecked") public <TYPE extends BaseMessage> TYPE markPrivileged() { this.effectiveUserId = Principals.systemUser().getName(); return (TYPE) this; }
/** * Evaluates the authorization for the operation requested, evaluates IAM, ACL, and bucket policy * (bucket policy not yet supported). * * @param request * @param bucketResourceEntity * @param objectResourceEntity * @param resourceAllocationSize the size for the quota check(s) if applicable * @return */ public <T extends ObjectStorageRequestType> boolean operationAllowed( @Nonnull T request, @Nullable final S3AccessControlledEntity bucketResourceEntity, @Nullable final S3AccessControlledEntity objectResourceEntity, long resourceAllocationSize) throws IllegalArgumentException { /* * Process the operation's authz requirements based on the request type annotations */ Ats requestAuthzProperties = Ats.from(request); ObjectStorageProperties.Permission[] requiredBucketACLPermissions = null; ObjectStorageProperties.Permission[] requiredObjectACLPermissions = null; Boolean allowOwnerOnly = null; RequiresACLPermission requiredACLs = requestAuthzProperties.get(RequiresACLPermission.class); if (requiredACLs != null) { requiredBucketACLPermissions = requiredACLs.bucket(); requiredObjectACLPermissions = requiredACLs.object(); allowOwnerOnly = requiredACLs.ownerOnly(); } else { // No ACL annotation is ok, maybe a admin only op } String[] requiredActions = null; RequiresPermission perms = requestAuthzProperties.get(RequiresPermission.class); if (perms != null) { requiredActions = perms.value(); } Boolean allowAdmin = (requestAuthzProperties.get(AdminOverrideAllowed.class) != null); Boolean allowOnlyAdmin = (requestAuthzProperties.get(AdminOverrideAllowed.class) != null) && requestAuthzProperties.get(AdminOverrideAllowed.class).adminOnly(); // Must have at least one of: admin-only, owner-only, ACL, or IAM. if (requiredBucketACLPermissions == null && requiredObjectACLPermissions == null && requiredActions == null && !allowAdmin) { // Insufficient permission set on the message type. LOG.error( "Insufficient permission annotations on type: " + request.getClass().getName() + " cannot evaluate authorization"); return false; } String resourceType = null; if (requestAuthzProperties.get(ResourceType.class) != null) { resourceType = requestAuthzProperties.get(ResourceType.class).value(); } // Use these variables to isolate where all the AuthExceptions can happen on account/user // lookups User requestUser = null; String securityToken = null; Account requestAccount = null; AuthContextSupplier authContext = null; try { // Use context if available as it saves a DB lookup try { Context ctx = Contexts.lookup(request.getCorrelationId()); requestUser = ctx.getUser(); securityToken = ctx.getSecurityToken(); requestAccount = requestUser.getAccount(); authContext = ctx.getAuthContext(); } catch (NoSuchContextException e) { requestUser = null; securityToken = null; requestAccount = null; authContext = null; } // This is not an expected path, but if no context found use the request credentials itself if (requestUser == null && !Strings.isNullOrEmpty(request.getEffectiveUserId())) { requestUser = Accounts.lookupUserById(request.getEffectiveUserId()); requestAccount = requestUser.getAccount(); } if (requestUser == null) { if (!Strings.isNullOrEmpty(request.getAccessKeyID())) { if (securityToken != null) { requestUser = SecurityTokenManager.lookupUser(request.getAccessKeyID(), securityToken); } else { requestUser = Accounts.lookupUserByAccessKeyId(request.getAccessKeyID()); } requestAccount = requestUser.getAccount(); } else { // Set to anonymous user since all else failed requestUser = Principals.nobodyUser(); requestAccount = requestUser.getAccount(); } } } catch (AuthException e) { LOG.error( "Failed to get user for request, cannot verify authorization: " + e.getMessage(), e); return false; } if (allowAdmin && requestUser.isSystemAdmin()) { // Admin override return true; } if (authContext == null) { authContext = Permissions.createAuthContextSupplier( requestUser, Collections.<String, String>emptyMap()); } Account resourceOwnerAccount = null; if (resourceType == null) { LOG.error("No resource type found in request class annotations, cannot process."); return false; } else { try { // Ensure we have the proper resource entities present and get owner info if (PolicySpec.S3_RESOURCE_BUCKET.equals(resourceType)) { // Get the bucket owner. if (bucketResourceEntity == null) { LOG.error( "Could not check access for operation due to no bucket resource entity found"); return false; } else { resourceOwnerAccount = Accounts.lookupAccountByCanonicalId(bucketResourceEntity.getOwnerCanonicalId()); } } else if (PolicySpec.S3_RESOURCE_OBJECT.equals(resourceType)) { if (objectResourceEntity == null) { LOG.error( "Could not check access for operation due to no object resource entity found"); return false; } else { resourceOwnerAccount = Accounts.lookupAccountByCanonicalId(objectResourceEntity.getOwnerCanonicalId()); } } } catch (AuthException e) { LOG.error("Exception caught looking up resource owner. Disallowing operation.", e); return false; } } // Get the resourceId based on IAM resource type String resourceId = null; if (resourceId == null) { if (PolicySpec.S3_RESOURCE_BUCKET.equals(resourceType)) { resourceId = request.getBucket(); } else if (PolicySpec.S3_RESOURCE_OBJECT.equals(resourceType)) { resourceId = request.getFullResource(); } } if (allowAdmin && requestUser.isSystemUser() && iamPermissionsAllow( authContext, requiredActions, resourceType, resourceId, resourceAllocationSize)) { // Admin override return true; } if (requiredBucketACLPermissions == null && requiredObjectACLPermissions == null) { throw new IllegalArgumentException( "No requires-permission actions found in request class annotations, cannot process."); } /* ACL Checks: Is the user's account allowed? */ Boolean aclAllow = false; if (requiredBucketACLPermissions != null && requiredBucketACLPermissions.length > 0) { // Check bucket ACLs if (bucketResourceEntity == null) { // There are bucket ACL requirements but no bucket entity to check. fail. // Don't bother with other checks, this is an invalid state LOG.error("Null bucket resource, cannot evaluate bucket ACL"); return false; } // Evaluate the bucket ACL, any matching grant gives permission for (ObjectStorageProperties.Permission permission : requiredBucketACLPermissions) { aclAllow = aclAllow || bucketResourceEntity.can(permission, requestAccount.getCanonicalId()); } } // Check object ACLs, if any if (requiredObjectACLPermissions != null && requiredObjectACLPermissions.length > 0) { if (objectResourceEntity == null) { // There are object ACL requirements but no object entity to check. fail. // Don't bother with other checks, this is an invalid state LOG.error("Null bucket resource, cannot evaluate bucket ACL"); return false; } for (ObjectStorageProperties.Permission permission : requiredObjectACLPermissions) { aclAllow = aclAllow || objectResourceEntity.can(permission, requestAccount.getCanonicalId()); } } /* Resource owner only? if so, override any previous acl decisions * It is not expected that owneronly is set as well as other ACL permissions, * Regular owner permissions (READ, WRITE, READ_ACP, WRITE_ACP) are handled by the regular acl checks. * OwnerOnly should be only used for operations not covered by the other Permissions (e.g. logging, or versioning) */ aclAllow = (allowOwnerOnly ? resourceOwnerAccount.getAccountNumber().equals(requestAccount.getAccountNumber()) : aclAllow); if (aclAllow && isUserAnonymous(requestUser)) { // Skip the IAM checks for anonymous access since they will always fail and aren't valid for // anonymous users. return true; } else { Boolean iamAllow = iamPermissionsAllow( authContext, requiredActions, resourceType, resourceId, resourceAllocationSize); // Must have both acl and iam allow (account & user) return aclAllow && iamAllow; } }
/** * Does the current request have an authenticated user? Or is it anonymous? * * @return */ protected static boolean isUserAnonymous(User usr) { return Principals.nobodyUser().equals(usr); }
protected static Address lookupOrCreate( final Cluster cluster, final ClusterAddressInfo addrInfo) { Address addr = null; VmInstance vm = null; try { addr = Addresses.getInstance().lookupDisabled(addrInfo.getAddress()); LOG.trace("Found address in the inactive set cache: " + addr); } catch (final NoSuchElementException e1) { try { addr = Addresses.getInstance().lookup(addrInfo.getAddress()); LOG.trace("Found address in the active set cache: " + addr); } catch (final NoSuchElementException e) { } } if (addrInfo.hasMapping()) { vm = Helper.maybeFindVm( addr != null ? addr.getInstanceId() : null, addrInfo.getAddress(), addrInfo.getInstanceIp()); if ((addr != null) && (vm != null)) { Helper.ensureAllocated(addr, vm); clearOrphan(addrInfo); } else if (addr != null && !addr.isPending() && vm != null && VmStateSet.DONE.apply(vm)) { handleOrphan(cluster, addrInfo); } else if ((addr != null && addr.isAssigned() && !addr.isPending()) && (vm == null)) { handleOrphan(cluster, addrInfo); } else if ((addr == null) && (vm != null)) { addr = new Address( Principals.systemFullName(), addrInfo.getAddress(), vm.getInstanceUuid(), vm.getInstanceId(), vm.getPrivateAddress()); clearOrphan(addrInfo); } else if ((addr == null) && (vm == null)) { addr = new Address(addrInfo.getAddress(), cluster.getPartition()); handleOrphan(cluster, addrInfo); } } else { if ((addr != null) && addr.isAssigned() && !addr.isPending()) { handleOrphan(cluster, addrInfo); } else if ((addr != null) && !addr.isAssigned() && !addr.isPending() && addr.isSystemOwned()) { try { addr.release(); } catch (final Exception ex) { LOG.error(ex); } } else if ((addr != null) && Address.Transition.system.equals(addr.getTransition())) { handleOrphan(cluster, addrInfo); } else if (addr == null) { addr = new Address(addrInfo.getAddress(), cluster.getPartition()); Helper.clearVmState(addrInfo); } } return addr; }
public boolean isSystemOwned() { return Principals.systemFullName().equals((UserFullName) this.getOwner()); }
public Address(final String ipAddress) { super(Principals.nobodyFullName(), ipAddress); }