@SuppressWarnings({"unchecked", "rawtypes"}) @Override public boolean apply(Class input) { if (Function.class.isAssignableFrom(input) && Ats.from(input).has(ErrorMessages.class)) { try { ErrorMessages annote = Ats.from(input).get(ErrorMessages.class); Function<Class, String> errorFunction = (Function<Class, String>) Classes.builder(input).newInstance(); ConcurrentMap<Class, String> errorMap = new MapMaker() .expireAfterAccess(60, TimeUnit.SECONDS) .makeComputingMap(errorFunction); classErrorMessages.put(annote.value(), errorMap); return true; } catch (UndeclaredThrowableException ex) { LOG.error(ex, ex); return false; } } else { Discovery discovery = Ats.from(ErrorMessageDiscovery.class).get(Discovery.class); LOG.error( "Annotated Discovery supplied class argument that does not conform to one of: value()=" + discovery.value() + " (assignable types) or annotations()=" + discovery.annotations()); return false; } }
private static FilteredPipeline findAccepting(final HttpRequest request) { final FilteredPipeline candidate = null; for (final FilteredPipeline f : pipelines) { if (f.checkAccepts(request)) { return f; } } if (request.getHeader(HttpHeaders.Names.HOST).contains("amazonaws.com") || request.getHeader(HttpHeaders.Names.HOST).contains(subDomain.get())) { String hostHeader = request.getHeader(HttpHeaders.Names.HOST); LOG.debug("Trying to intercept request for " + hostHeader); for (final FilteredPipeline f : pipelines) { if (Ats.from(f).has(ComponentPart.class)) { Class<? extends ComponentId> compIdClass = Ats.from(f).get(ComponentPart.class).value(); ComponentId compId = ComponentIds.lookup(compIdClass); if (Ats.from(compIdClass).has(PublicService.class)) { if (request.getHeaderNames().contains("SOAPAction") && f.addHandlers(Channels.pipeline()).get(SoapHandler.class) == null) { continue; // Skip pipeline which doesn't handle SOAP for this SOAP request } else if (!request.getHeaderNames().contains("SOAPAction") && f.addHandlers(Channels.pipeline()).get(SoapHandler.class) != null) { continue; // Skip pipeline which handles SOAP for this non-SOAP request } LOG.debug("Maybe intercepting: " + hostHeader + " using " + f.getClass()); if (Ats.from(compIdClass).has(AwsServiceName.class) && request .getHeader(HttpHeaders.Names.HOST) .matches( "[\\w\\.-_]*" + compId.getAwsServiceName() + "\\.\\w+\\.amazonaws.com")) { return f; // Return pipeline which can handle the request for // ${service}.${region}.amazonaws.com } else if (request .getHeader(HttpHeaders.Names.HOST) .matches("[\\w\\.-_]*" + compId.name() + "\\." + subDomain.get())) { return f; // Return pipeline which can handle the request for // ${service}.${system.dns.dnsdomain} } } } } } if (candidate == null) { for (final FilteredPipeline f : internalPipelines) { if (f.checkAccepts(request)) { return f; } } } return candidate; }
static String lookatPersistenceContext(final Object obj) throws RuntimeException { final Class type = Classes.typeOf(obj); final Ats ats = Ats.inClassHierarchy(type); PersistenceContext persistenceContext = null; if (!ats.has(PersistenceContext.class)) { throw new RuntimeException( "Attempting to create an entity wrapper instance for non persistent type: " + type + ". Class hierarchy contains: \n" + ats.toString()); } else { persistenceContext = ats.get(PersistenceContext.class); } return persistenceContext.name(); }
public String process() { if (this.type.getCanonicalName() == null) { // new RuntimeException( "Ignoring anonymous class: " + this.type // ).printStackTrace( ); } else { this.elem(Elem.mapping); if (this.abs) { this.attr("abstract", "true"); } else { this.attr("name", this.type.getSimpleName()) .attr("extends", this.type.getSuperclass().getCanonicalName()); } this.attr("class", this.type.getCanonicalName()); if (BindingFileSearch.INSTANCE.MSG_BASE_CLASS.isAssignableFrom(this.type.getSuperclass()) || BindingFileSearch.INSTANCE.MSG_DATA_CLASS.isAssignableFrom( this.type.getSuperclass())) { this.elem(Elem.structure) .attr("map-as", this.type.getSuperclass().getCanonicalName()) .end(); } for (Field f : this.type.getDeclaredFields()) { if (!Ats.from(f).has(Transient.class) || Modifier.isTransient(f.getModifiers())) { TypeBinding tb = getTypeBinding(f); if (!(tb instanceof NoopTypeBinding)) { // System.out.printf( "BOUND: %-70s [type=%s:%s]\n", // f.getDeclaringClass( ).getCanonicalName( ) +"."+ f.getName( ), tb.getTypeName( ), // f.getType( ).getCanonicalName( ) ); this.append(tb.toString()); } } } this.end(); } return this.toString(); }
@Override public boolean processClass(Class candidate) throws Exception { if (Ats.from(candidate).has(ObjectStorageProviderClientProperty.class) && !Modifier.isAbstract(candidate.getModifiers()) && !Modifier.isInterface(candidate.getModifiers())) { ObjectStorageProviderClientProperty candidateType = Ats.from(candidate).get(ObjectStorageProviderClientProperty.class); String propName = candidateType.value(); if (ObjectStorageProviderClient.class.isAssignableFrom(candidate)) { clients.put(propName, candidate); } return true; } else { return false; } }
@SuppressWarnings({"rawtypes", "unchecked", "synthetic-access"}) @Override public boolean processClass(final Class candidate) throws Exception { if (FilteredPipeline.class.isAssignableFrom(candidate) && !Modifier.isAbstract(candidate.getModifiers()) && !Modifier.isInterface(candidate.getModifiers()) && Ats.from(candidate).has(ComponentPart.class)) { try { final ComponentId compId = Ats.from(candidate).get(ComponentPart.class).value().newInstance(); final Class<? extends FilteredPipeline> pipelineClass = candidate; final FilteredPipeline pipeline = Classes.newInstance(pipelineClass); Pipelines.pipelines.add(pipeline); return true; } catch (final Exception ex) { LOG.trace(ex, ex); return false; } } else if (ChannelPipelineFactory.class.isAssignableFrom(candidate) && !Modifier.isAbstract(candidate.getModifiers()) && !Modifier.isInterface(candidate.getModifiers()) && Ats.from(candidate).has(ComponentPart.class)) { try { final ComponentId compId = Ats.from(candidate).get(ComponentPart.class).value().newInstance(); final Class<? extends ChannelPipelineFactory> pipelineClass = candidate; final ChannelPipelineFactory pipeline = Classes.newInstance(pipelineClass); Pipelines.clientPipelines.put(compId.getClass(), pipeline); return true; } catch (final Exception ex) { LOG.trace(ex, ex); return false; } } else { return false; } }
@SuppressWarnings("ThrowableResultOfMethodCallIgnored") public void handle(final ExceptionMessage exMsg) { EventRecord.here(getClass(), EventType.MSG_REPLY, exMsg.getPayload().getClass().getSimpleName()) .debug(); LOG.trace("Caught exception while servicing: " + exMsg.getPayload()); final Throwable exception = exMsg.getException(); if (exception instanceof MessagingException && exception.getCause() instanceof EucalyptusCloudException) { try { final EucalyptusCloudException cloudException = (EucalyptusCloudException) exception.getCause(); final BaseMessage payload = parsePayload(exMsg.getPayload()); final HttpResponseStatus status; final Role role; final String code; if (cloudException instanceof EucalyptusWebServiceException) { final EucalyptusWebServiceException webServiceException = (EucalyptusWebServiceException) cloudException; role = webServiceException.getRole(); code = webServiceException.getCode(); } else { role = Role.Receiver; code = defaultCode; } final QueryBindingInfo info = Ats.inClassHierarchy(cloudException.getClass()).get(QueryBindingInfo.class); status = info == null ? HttpResponseStatus.INTERNAL_SERVER_ERROR : new HttpResponseStatus(info.statusCode(), code); final BaseMessage errorResp = buildErrorResponse(payload.getCorrelationId(), role, code, cloudException.getMessage()); Contexts.response(new BaseMessageSupplier(errorResp, status)); } catch (final PayloadParseException e) { LOG.error("Failed to parse payload ", e.getCause()); } } else { LOG.error("Unable to handle exception", exception); final BaseMessage errorResp = buildFatalResponse(exception); Contexts.response( new BaseMessageSupplier(errorResp, HttpResponseStatus.INTERNAL_SERVER_ERROR)); } }
@Override public void handleUpstream( final ChannelHandlerContext channelHandlerContext, final ChannelEvent channelEvent) throws Exception { if (channelEvent instanceof MessageEvent && componentIdClass != null) { final BaseMessage message = BaseMessage.extractMessage(channelEvent); final ComponentMessage componentMessage = message == null ? null : Ats.inClassHierarchy(message.getClass()).get(ComponentMessage.class); if (message != null && (componentMessage == null || !componentIdClass.equals(componentMessage.value()))) { LOG.warn( String.format( "Message %s does not match pipeline component %s", message.getClass(), componentIdClass.getSimpleName())); final MappingHttpMessage mappingHttpMessage = MappingHttpMessage.extractMessage(channelEvent); final BaseMessage baseMessage = BaseMessage.extractMessage(channelEvent); if (baseMessage != null) { Contexts.clear(Contexts.lookup(baseMessage.getCorrelationId())); } channelHandlerContext .getChannel() .write( new MappingHttpResponse( mappingHttpMessage == null ? HttpVersion.HTTP_1_1 : mappingHttpMessage.getProtocolVersion(), HttpResponseStatus.BAD_REQUEST)); return; } } channelHandlerContext.sendUpstream(channelEvent); }
/** * 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; } }
@Override public PolicyKey apply(final Class<? extends Key> keyClass) { return Ats.from(keyClass).get(PolicyKey.class); }