How to get GCP Audit Log status programmatically - go

I'm trying to get a list of Audit Logs similar to what is displayed in Google console page (IAM/Audit Logs) using the Golang API GetIamPolicy as described here:
https://cloud.google.com/resource-manager/reference/rest/v1/projects/getIamPolicy
If one service has at least one of its Log Types set (Data Read, Data Write or Admin Read), GetIamPolicy will return it, but if it does not have any set then the service is omitted from the response.
As an example, if my project has three services A, B and C and A has Data Read enabled, B has Admin Read enabled and C doesn't have anything enabled, GetIamPolicy will only return A and B.
GetIamPolicyRequest struct seems to have fields designed for this scenario (NullFields and ForceSendFields), but I couldn't make it work. Example:
rb := &cloudresourcemanager.GetIamPolicyRequest{}
rb.ForceSendFields = []string{"LogType"}
rb.NullFields = []string{"LogType"}
policyOptions := &cloudresourcemanager.GetPolicyOptions{}
policyOptions.ForceSendFields = []string{"LogType"}
policyOptions.NullFields = []string{"LogType"}
policyOptions.RequestedPolicyVersion = 3
rb.Options = policyOptions
Any ideas on how to retrieve the missing services?

Related

Reading CloudWatch log query status in go SDK v2

I'm running a CloudWatch log query through the v2 SDK for Go. I've successfully submitted the query using the StartQuery method, however I can't seem to process the results.
I've got my query ID in a variable (queryID) and am using the GetQueryResults method as follows:
results, err := svc.GetQueryResults(context.TODO(), &cloudwatchlogs.GetQueryResultsInput{QueryId: queryId,})
How do I actually read the contents? Specifically, I'm looking at the Status field. If I run the query at the command line, this comes back as a string description. According to the SDK docs, this is a bespoke type "QueryStatus", which is defined as a string with enumerated constants.
I've tried comparing to the constant names, e.g.
if results.Status == cloudwatchlogs.GetQueryResultsOutput.QueryStatus.QueryStatusComplete
but the compiler doesn't accept this. How do I either reference the constants or get to the string value itself?
The QueryStatus type is defined in the separate types package. The Go SDK services are all organised this way.
import "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
if res.Status == types.QueryStatusComplete {
fmt.Println("complete!")
}

Can I record workout data to GoogleFit from WearOS app?

I'm making a fitness wearOS app.
I want to record workouts completed with the app to GoogleFit.
Is there a way to do that from WearOS?
I start a workout using HealthServices:
suspend fun startExercise() {
val dataTypes = setOf(
DataType.HEART_RATE_BPM,
DataType.LOCATION
)
val aggregateDataTypes = setOf(
DataType.DISTANCE,
DataType.TOTAL_CALORIES
)
val config = ExerciseConfig.builder()
.setExerciseType(ExerciseType.RUNNING)
.setDataTypes(dataTypes)
.setAggregateDataTypes(aggregateDataTypes)
.setShouldEnableAutoPauseAndResume(false)
.setShouldEnableGps(true)
.build()
HealthServices.getClient(this /*context*/)
.exerciseClient
.startExercise(config)
.await()
}
(Code is from this example https://developer.android.com/training/wearables/health-services/active#start)
I was expecting if I would start/end a workout with HealthServices it would auto-magically sync the data to GoogleFit(Apple does this with for HealthKit).
So, can I record workout data to GoogleFit from a WearOS app?
To add to the Yuri's comment that this isn't possible automatically, the SessionClient is probably what you'd want in order to do this manually. The flow would be:
Collect data with Health Services
Transform
Insert session with SessionClient
The insert a session snippet in the Google Fit docs is a relevant example, as it both sets the session type (in this case, running) and then also adds the underlying data (instead of doing that separately with HistoryClient).
Update: You may also wish to take a look at Health Connect, which was recently announced.

how can I get ALL records from route53?

how can I get ALL records from route53?
referring code snippet here, which seemed to work for someone, however not clear to me: https://github.com/aws/aws-sdk-ruby/issues/620
Trying to get all (I have about ~7000 records) via resource record sets but can't seem to get the pagination to work with list_resource_record_sets. Here's what I have:
route53 = Aws::Route53::Client.new
response = route53.list_resource_record_sets({
start_record_name: fqdn(name),
start_record_type: type,
max_items: 100, # fyi - aws api maximum is 100 so we'll need to page
})
response.last_page?
response = response.next_page until response.last_page?
I verified I'm hooked into right region, I see the record I'm trying to get (so I can delete later) in aws console, but can't seem to get it through the api. I used this: https://github.com/aws/aws-sdk-ruby/issues/620 as a starting point.
Any ideas on what I'm doing wrong? Or is there an easier way, perhaps another method in the api I'm not finding, for me to get just the record I need given the hosted_zone_id, type and name?
The issue you linked is for the Ruby AWS SDK v2, but the latest is v3. It also looks like things may have changed around a bit since 2014, as I'm not seeing the #next_page or #last_page? methods in the v2 API or the v3 API.
Consider using the #next_record_name and #next_record_type from the response when #is_truncated is true. That's more consistent with how other paginations work in the Ruby AWS SDK, such as with DynamoDB scans for example.
Something like the following should work (though I don't have an AWS account with records to test it out):
route53 = Aws::Route53::Client.new
hosted_zone = ? # Required field according to the API docs
next_name = fqdn(name)
next_type = type
loop do
response = route53.list_resource_record_sets(
hosted_zone_id: hosted_zone,
start_record_name: next_name,
start_record_type: next_type,
max_items: 100, # fyi - aws api maximum is 100 so we'll need to page
)
records = response.resource_record_sets
# Break here if you find the record you want
# Also break if we've run out of pages
break unless response.is_truncated
next_name = response.next_record_name
next_type = response.next_record_type
end

How should I test if a PDU is too big in WinSNMP?

I am building an SNMP Agent for a Windows application using the Microsoft WinSNMP API. Currently everything is working for single-item get and set-request, and also for get-next to allow walking the defined tree (albeit with some caveats that are not relevant to this question).
I am now looking at multi-item get and also get-bulk.
My current procedure is to iterate through the list of requested items (the varbindlist within the PDU), treating each one individually, effectively causing an internal get. The result is added to the VBL, set into the PDU, and then sent back to the SNMP Manager, taking into account invalid requests, etc.
My question is how should I handle "too much" data (data that cannot fit into a single transport layer message)? Or more accurately, is there a way to test whether data is "too big" without actually attempting to transmit? The only way I can see in the API is to try sending, check the error, and try again.
In the case of a get-request this isn't a problem - if you can't return all of the requested data, you fail: so attempt sending, and if the error report is SNMPAPI_TL_PDU_TOO_BIG, send a default "error" PDU.
However, it is allowable for a response to bulk-get to return partial results.
The only way I can see to handle this is a tedious (?) loop of removing an item and trying again. Something similar to the following (some detail removed for brevity):
// Create an empty varbindlist
vbl = SnmpCreateVbl(session, NULL, NULL);
// Add all items to the list
SnmpSetVb(vbl, &oid, &value); // for each OID/Value pair
// Create the PDU
pdu = SnmpCreatePdu(session, SNMP_PDU_RESPONSE, ..., vbl);
bool retry;
do {
retry = false;
smiINT failed = SnmpSendMsg(session, ..., pdu);
if (failed && SNMPAPI_TL_PDU_TOO_BIG == SnmpGetLastError()) {
// too much data, delete the last vb
SnmpDeleteVb(vbl, SnmpCountVbl(vbl));
SnmpSetPduData(pdu, ..., vbl);
retry = true;
};
} while(retry);
This doesn't seem like an optimal approach - so is there another way that I've missed?
As a side-note, I know about libraries such as net-snmp, but my question is specific to the Microsoft API.
The RFC does require you to do what you pasted,
https://www.rfc-editor.org/rfc/rfc3416
Read page 16.
There does not seem to be a function exposed by WinSNMP API that can do this for you, so you have to write your own logic to handle it.

Simple Claims Transformation for an RP-STS in Geneva Framework

After reading the MSDN article (http://msdn.microsoft.com/en-us/magazine/2009.01.genevests.aspx) on implementing a Custom STS using the Microsoft Geneva Framework I am a bit puzzled about one of the scenarios covered there. This scenario is shown in figure 13 of the above referenced article.
My questions are around how does the RP initiate the call to the RP-STS in order to pass on the already obtained claims from the IP-STS? How does the desired method DeleteOrder() get turned into a Claim Request for the Action claim from the RP-STS which responds with the Action claim with a value Delete which authorizes the call? I also think the figure is slightly incorrect in that the interaction between the RP-STS and the Policy Engine should have the Claims and arrows the other way around.
I can see the structure but it's not clear what is provided by Geneva/WCF and what has to be done in code inside the RP, which would seem a bit odd since we could not protect the DeleteOrder method with a PrincipalPermission demand for the Delete "permission" but would have to demand a Role first then obtain the fine-grained claim of the Delete Action after that point.
If I have missed the point (since I cannot find this case covered easily on the Web), then apologies!
Thanks in advance.
I asked the same question on the Geneva Forum at
http://social.msdn.microsoft.com/Forums/en/Geneva/thread/d10c556c-1ec5-409d-8c25-bee2933e85ea?prof=required
and got this reply:
Hi Dokie,
I wondered this same thing when I read that article. As I've pondered how such a scenario would be implemented, I've come up w/ two ideas:
The RP is actually configured to require claims from the RP-STS; the RP-STS requires a security token from the IP-STS. As a result, when the subject requests a resource of the RP, it bounces him to the RP-STS who bounces him to the IP-STS. After authenticating there, he is bounced back to the RP-STS, the identity-centric claims are transformed into those necessary to make an authorization decision and returned to the RP.
The RP is configured to have an interceptor (e.g., an AuthorizationPolicy if it's a WCF service) that grabs the call, sees the identity-centric claims, creates an RST (using the WSTrustClient), passes it to the RP-STS, that service expands the claims into new one that are returned to the RP, and the RP makes an authorization decision.
I've never implemented this, but, if I were going to, I would explore those two ideas further.
HTH!
Regards,
Travis Spencer
So I will try option 2 first and see if that works out then formulate an answer here.
I've got situation one working fine.
In my case AD FS is the Identity Service and a custom STS the Resource STS.
All webapp's use the same Resource STS, but after a user visits an other application the Identity releated claims are not addad again by the AD FS since the user is already authenticated. How can I force or request the basic claims from the AD FS again?
I've created a call to the AD FS with ActAs, now it returns my identification claims.
Remember to enable a Delegation allowed rule for the credentials used to call the AD FS.
string stsEndpoint = "https://<ADFS>/adfs/services/trust/2005/usernamemixed";
var trustChannelFactory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), stsEndpoint);
trustChannelFactory.Credentials.UserName.UserName = #"DELEGATE";
trustChannelFactory.Credentials.UserName.Password = #"PASSWORD";
trustChannelFactory.TrustVersion = TrustVersion.WSTrustFeb2005;
//// Prepare the RST.
//var trustChannelFactory = new WSTrustChannelFactory(tokenParameters.IssuerBinding, tokenParameters.IssuerAddress);
var trustChannel = (WSTrustChannel)trustChannelFactory.CreateChannel();
var rst = new RequestSecurityToken(RequestTypes.Issue);
rst.AppliesTo = new EndpointAddress(#"https:<RPADDRESS>");
// If you're doing delegation, set the ActAs value.
var principal = Thread.CurrentPrincipal as IClaimsPrincipal;
var bootstrapToken = principal.Identities[0].BootstrapToken;
// The bootstraptoken is the token received from the AD FS after succesfull authentication, this can be reused to call the AD FS the the users credentials
if (bootstrapToken == null)
{
throw new Exception("Bootstraptoken is empty, make sure SaveBootstrapTokens = true at the RP");
}
rst.ActAs = new SecurityTokenElement(bootstrapToken);
// Beware, this mode make's sure that there is no certficiate needed for the RP -> AD FS communication
rst.KeyType = KeyTypes.Bearer;
// Disable the need for AD FS to crypt the data to R-STS
Scope.SymmetricKeyEncryptionRequired = false;
// Here's where you can look up claims requirements dynamically.
rst.Claims.Add(new RequestClaim(ClaimTypes.Name));
rst.Claims.Add(new RequestClaim(ClaimTypes.PrimarySid));
// Get the token and attach it to the channel before making a request.
RequestSecurityTokenResponse rstr = null;
var issuedToken = trustChannel.Issue(rst, out rstr);
var claims = GetClaimsFromToken((GenericXmlSecurityToken)issuedToken);
private static ClaimCollection GetClaimsFromToken(GenericXmlSecurityToken genericToken)
{
var handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
var token = handlers.ReadToken(new XmlTextReader(new StringReader(genericToken.TokenXml.OuterXml)));
return handlers.ValidateToken(token).First().Claims;
}

Resources