Cannot set `bearerOnly: true` in Keycloak 19.0 - keycloak

I am trying to secure my backend service but due to the updates with Keycloak 19.0 I can't follow any tutorial online. I am trying to set bearerOnly: true but there are no options to set the access type in new version of Keycloak

I tested v19.0.1, I can't find to option for bearerOnly option UI either but client JSON import after export and change bearerOnly true works.
I tested to import v18.0.2's JSON makes error.(attached image at the bottom)
So if you migrate from old version to 19.0.1 should be update manually base on v19's export JSON file.
Steps
Export Client JSON from v19
Delete #1 client
Switch "bearerOnly": true
Import #3 JSON in v19
This is bearerOnly true and false difference screen in UI
bearerOnly True option
bearerOnly False option
Using this JSON for True option
{
"clientId": "my-client-bearer-true",
"name": "My Client Bearer Only True",
"description": "",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": true,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": true,
"protocol": "openid-connect",
"attributes": {
"oidc.ciba.grant.enabled": "false",
"oauth2.device.authorization.grant.enabled": "false",
"backchannel.logout.session.required": "true",
"backchannel.logout.revoke.offline.tokens": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"defaultClientScopes": [
"web-origins",
"acr",
"roles",
"profile",
"email"
],
"optionalClientScopes": [
"address",
"phone",
"offline_access",
"microprofile-jwt"
],
"access": {
"view": true,
"configure": true,
"manage": true
}
}
If import v18.0.2 JSON file with bearerOnly true into v19.0.1,
It makes error
I using this V18 JSON file but It makes error as upper image.
So you can't import directly v18 JSON into V19.
{
"realm": "test",
"bearer-only": true,
"auth-server-url": "http://localhost:8180/auth/",
"ssl-required": "external",
"resource": "my-client",
"confidential-port": 0
}

Related

Keycloak SAML Client is not showing the login screen

I have created a realm in Keycloak named SAML-Demo-Py
In the realm I have created a SAML client with these configuration
{
"clientId": "http://localhost:8081/python-app",
"name": "test-client-saml",
"description": "",
"rootUrl": "",
"adminUrl": "http://localhost:8081/cgi-bin/saml-consumer.py",
"baseUrl": "",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [
"http://localhost:8081/cgi-bin/saml-consumer.py"
],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": true,
"protocol": "saml",
"attributes": {
"saml_assertion_consumer_url_redirect": "http://localhost:8081/cgi-bin/saml-consumer.py",
"saml.force.post.binding": "true",
"saml.server.signature.keyinfo.ext": "false",
"saml.signing.certificate": "MIICzzCCAbcCBgGDSplRlDANBgkqhkiG9w0BAQsFADArMSkwJwYDVQQDDCBodHRwOi8vbG9jYWxob3N0OjgwODEvcHl0aG9uLWFwcDAeFw0yMjA5MTcwODM2NDVaFw0zMjA5MTcwODM4MjVaMCsxKTAnBgNVBAMMIGh0dHA6Ly9sb2NhbGhvc3Q6ODA4MS9weXRob24tYXBwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAve0sgrdPWvcKiRJ5UPcpa301aiIO7F7KDKnMDtxgY2EE47z8XS5TUvvySa75L0phxZQv+iqYSV1HlUkgJQiax3fg7JgxJ+BY3ss9Dz/m9x7stErFoMXeH+Bhdk9H7hUojlRqxn8qU7ZwInENvw8hlzTgouc5hqqBaQybXqtlmJi6HWAH/3Ck6jCd+P6pjIaGrQpYxpmpmPKbhRnovZWgL6KqdnoEl1thEcPAEbXE7HiB6h4z9HdF2EWx/8U7HE/qCq2m2lPsKn2OnJk2ejDqa5SyTBXRqeqS8sG70VXrotEtJVVuPJCFvGy8r7mq0bVX/83y+PyEpppsJMMtockdgwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBEDptd2Goi1XFKur3dpRHyOW9zxs96gGGllrcnQZCtZjVEb31Jibr0HFDftHR22hQV1mbQLokNk8k0on7tJvsOIdXv3459gkZyouYSmYpDTvfCi3YUgdxVrDiHzwaN6uIjqXeDeI08LmH2xDZwac46vqJyqx3QI/r84qmWR2Nil/7DnJegVWyr961GWm0HH6BpweZZ5QbEw0UHihqWDthgX4BAmVnRPm9fHebIa3/7AUqodh8hoRDJcaDiyLB+V8nUPD6vLwgFgiLSqLSPaJ0OSzBvz3cpNLL1PVkFVaoQZ7W3FX6Ruvz0Bj/piQ+h2fnX4NMkj33f6CyhJTGSfbnk",
"saml$server$signature$keyinfo$ext": "false",
"saml.signature.algorithm": "RSA_SHA256",
"saml.client.signature": "false",
"saml.force.name.id.format": "false",
"saml.signing.private.key": "MIIEowIBAAKCAQEAve0sgrdPWvcKiRJ5UPcpa301aiIO7F7KDKnMDtxgY2EE47z8XS5TUvvySa75L0phxZQv+iqYSV1HlUkgJQiax3fg7JgxJ+BY3ss9Dz/m9x7stErFoMXeH+Bhdk9H7hUojlRqxn8qU7ZwInENvw8hlzTgouc5hqqBaQybXqtlmJi6HWAH/3Ck6jCd+P6pjIaGrQpYxpmpmPKbhRnovZWgL6KqdnoEl1thEcPAEbXE7HiB6h4z9HdF2EWx/8U7HE/qCq2m2lPsKn2OnJk2ejDqa5SyTBXRqeqS8sG70VXrotEtJVVuPJCFvGy8r7mq0bVX/83y+PyEpppsJMMtockdgwIDAQABAoIBABjRKm1ELarZt/c0QkTpnvBsMnQVUjThp+4iq8bPVgr2TPDDK4izenDP+hdVtTrQMdli5Sf/s9l2RlnD7d7Y8nyY9fuEYXvv7Tzjeq2I8JGe6VgfoxZAdKdepu2SK3h5LEz4y+D3Ed1Ra/KcKisqe32qC6ZNp28ozXMgEhc7NzHKnOxKA0IXFzuT6cDJgJ8TQfa2K9dGgjEE9GTCCxnZEvdf17sEc4zVMJDDcE4Rorv0mZeN1QRXVSpnW1q0vFh1CvH1H9oBCUey8cElQybARTDbMJJWgHCdd29EbilmlyB4TFI34tcaKZUlvL3sT8fvRyV6yLL0M0mqVWYxhu24naUCgYEA/WKH8G6SsM+LhC2oVJWUSDicpDNNEi2Av2FZOSg7Vbqj53/t69kSPWv0Rp0o7Bz55xwxH+n6PjUEvHyiS3UBIW6kS81av1H8Gle/1XpopHEY4aX47KCdF1Wc0yq8l5ii+oFZt3GcS1egDFPiQgyo2lhlrrQ4mckcSZF3pdd8UTUCgYEAv+L6qdXxPZvyzRgsRfhmVl8FKdKPYFqBWQgh2Lx21J16T8jRhjFfJP6NNi2JupWrQB2JdA5sivx81GMxExo5j8P1VQm/g/c3I2bxb1kYDE77x6KJzmr0i7hK0SEGCcP51EdVpjtPzcdG3st3GT5UClvZ+rTfO87e6n4pdlMUgtcCgYBUre8cTPe9Gz9XByMwUWTi1fiTb4mcP5S9YL0+utFJjzxji39pyHuuBzv1tWQNtIlX0TYhokI9M97HVyet7AZas+04YAKp2a5U52p235fFDP7xulP8UJjvSW9Fqwyn5RzidwQSqGdBTqFwPUBqLmznu48P2a7oxisr8u93fxJO2QKBgG0fkdl/139n7n6AXr0z9E7uHquYGP18us5893KgSxvCqsowtCcScL9DG99Rql+3ufnuUjrz8PpheEP4XPI2GcIOeLhxoL5Vmr/BTVA7ZJerWzg+0QvYe1Xx6mpf02U+VBdKsgSk+k9WIpGVOBfdAEIb1izjK4iBrve/46hsut9lAoGBAKeKxXlH45BTuRg/Rcp60TTV4i+Aed0ApTmvYU22XasXRfrFsauLaxUkCP0x0hvdVx+cR37Jo9Nfw9DmplzHLVMI6STzracLuhjf0HKVS6XSJa5l4VpsmkJaWxyqdrm91OXnOOizTf6pOoRFoFI21u7ZKqMoEcaqrCOIwqv21qpa",
"saml.allow.ecp.flow": "false",
"saml.server.signature.keyinfo.xmlSigKeyInfoKeyNameTransformer": "NONE",
"saml.assertion.signature": "true",
"saml.encrypt": "false",
"login_theme": "keycloak",
"saml_assertion_consumer_url_post": "http://localhost:8081/cgi-bin/saml-consumer.py",
"saml$server$signature": "true",
"saml.server.signature": "true",
"saml.artifact.binding.identifier": "90y02x5M6keohgaOI7l3D0ZpdfU=",
"saml$server$signature$keyinfo$xmlSigKeyInfoKeyNameTransformer": "NONE",
"saml.artifact.binding": "false",
"saml_force_name_id_format": "false",
"saml.authnstatement": "true",
"display.on.consent.screen": "false",
"saml_name_id_format": "username",
"saml.onetimeuse.condition": "false",
"saml_signature_canonicalization_method": "http://www.w3.org/2001/10/xml-exc-c14n#"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"defaultClientScopes": [
"role_list"
],
"optionalClientScopes": [],
"access": {
"view": true,
"configure": true,
"manage": true
}
}
I have a running python dummy app which will act as ACS.
This is the SAML Request which will be send from the browser in the form of
<IDP-sso-url>?SAMLRequest=<encoded-same-request>
which results in
http://localhost:8080/realms/SAML-Demp-Py?SAMLRequest=lVLLTsMwEPyVyHfXSZpCayWVSiNEJEBRKRy4INdZqIVjB6%2FD4%2B9xUpDKBcHNK8%2FMzow2R9Hqjq96vzcbeOkBffTeaoN8%2FChI7wy3AhVyI1pA7iW%2FWV1d8nQS885Zb6XV5ED5HSwQwXllDTla8GfK6vu5tgb7FtwNuFcl4XZzWZC99x1nTFsp9N6i5%2FN4HjMHQrfIBjVaQtvR%2BoPtnH0Gx4bVVDUd9SEvA9N0VhlPojKMyohhzz9USXRunYSxw4I8Co1AoqosSFU%2BxMluOltAQuOTpKEZwIyKTIYxyzKxkDJtxGkAI%2FZQGfTC%2BIKkcZrSeEGT022S8GnM05PJdDG%2FJ1H9VfiZMo0yT7%2B3tzuAkF9stzXdQKMcyBDyDhyOAQOILPOhCz4acMs%2FR87ZMS0%2FHNF1sFCVtdVKfkQrre3bOlA9FMS7HsaWWhHy1YMB9BAaZ8uD0s8LXH4C&RelayState=9UITFKRCV-uUX7vdyNF6xIEybOVX2uDNZVohLi5OenU.q8U2Lp-_Lg8.http%3A%2F%2Flocalhost%3A8081%2Fpython-app
This is the request before encoding
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
AssertionConsumerServiceURL="http://localhost:8081/cgi-bin/saml-consumer.py"
Destination="http://localhost:8080/realms/SAML-Demp-Py/protocol/saml"
ID="1234"
IssueInstant="2021-09-17T18:41:20.295Z"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Version="2.0">
<saml2:Issuer
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8081/python-app
</saml2:Issuer>
</saml2p:AuthnRequest>
Now once past this in the url I don't see the keycloak login screen. Instead the url in the browser is still the same as above and I see this json in the body of the page
{"realm":"SAML-Demp-Py","public_key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvvoRDqFxcnJAmISv4qequAJ4w1dubE47Z2RStqVQ7oUZaUPO2magxvfa8CyaEwHuySkn42NjrafVMhZp/0gBVtsVW4uwNJCMXjvv8Tfbd4qUtVo50mEgGIpJRsm5RPXUJX2q1Yz/jX+U2vTfutEIDpRZGF6PtHt/tavuGt+qohpRycTWFvcEU7LuVu7Sj7AaOBNpgGSITUEYc09+JwrWcbenhrBZq9mJ5hgCw/0TU+HcwCIi1XgUVrzZ6OG0DwE702ezuDP2Nbs78U0w6tHUj+B1+p/TAntIg39CiwHHL3kIcwwJpHiJmeLNTlwlQm+Ny3w9LmP09dPAjMm2lw1qywIDAQAB","token-service":"http://localhost:8080/realms/SAML-Demp-Py/protocol/openid-connect","account-service":"http://localhost:8080/realms/SAML-Demp-Py/account","tokens-not-before":0}
You are using wrong endpoint. It is:
http://localhost:8080/realms/SAML-Demp-Py/protocol/saml?SAMLRequest=<encoded-saml-request>
instead of:
http://localhost:8080/realms/SAML-Demp-Py?SAMLRequest=<encoded-saml-request>

Configuring keycloak as IDP in another keycloak

I am trying to configure a keycloak as an IDP in another keycloak. In my test setup there are 2 keycloak containers - keycloak-1 and keycloak-2.
In keycloak-1, I have created an openid client called idp-client. The configuration exported as JSON is shown below,
{
"clientId": "idp-client",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [
"http://localhost:8081/auth/realms/master/broker/oidc/endpoint"
],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": false,
"publicClient": false,
"frontchannelLogout": false,
"protocol": "openid-connect",
"attributes": {
"saml.assertion.signature": "false",
"saml.force.post.binding": "false",
"saml.multivalued.roles": "false",
"saml.encrypt": "false",
"saml.server.signature": "false",
"saml.server.signature.keyinfo.ext": "false",
"exclude.session.state.from.auth.response": "false",
"saml_force_name_id_format": "false",
"saml.client.signature": "false",
"tls.client.certificate.bound.access.tokens": "false",
"saml.authnstatement": "false",
"display.on.consent.screen": "false",
"saml.onetimeuse.condition": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"defaultClientScopes": [
"web-origins",
"role_list",
"profile",
"roles",
"email"
],
"optionalClientScopes": [
"address",
"phone",
"offline_access",
"microprofile-jwt"
],
"access": {
"view": true,
"configure": true,
"manage": true
}
}
In keycloak-2, I have added keycloak-1 as an identity provider. I have attached the images of the configuration for reference.
Now when I try to login to keycloak-2 using keycloak-1's user, after successful login, I am redirected to keycloak-2's but to an error page, its showing "Unexpected error when authenticating with identity provider"
Stacktrace in the keycloak-2's terminal is as below,
keycloak2_1 | 08:21:17,079 TRACE [org.keycloak.events] (default task-10) type=CODE_TO_TOKEN_ERROR, realmId=master, clientId=idp-client, userId=null, ipAddress=127.0.0.1, error=invalid_client_credentials, grant_type=authorization_code, requestUri=http://localhost:8080/auth/realms/master/protocol/openid-connect/token, cookies=[]
...
...
keycloak2_1 | 08:21:17,081 TRACE [org.keycloak.events] (default task-12) type=LOGIN_ERROR, realmId=master, clientId=null, userId=null, ipAddress=172.21.0.1, error=identity_provider_login_failure, requestUri=http://localhost:8081/auth/realms/master/broker/oidc/endpoint?state=MOz5_i2-SpoSLRtS4IWkXtUBsSzGciBysUrdYq8gGy0.k0e5WlQElRw.security-admin-console&session_state=1cc90330-cf3c-45c3-a44e-53fc71b17bb1&code=be12828b-3408-4822-b275-31afeb1c0405.1cc90330-cf3c-45c3-a44e-53fc71b17bb1.eb068c43-9f4e-45b7-b2e8-ac346f139141, cookies=[KEYCLOAK_SESSION_LEGACY=master/ce30941f-407f-4344-9019-58d2f26ea832/1cc90330-cf3c-45c3-a44e-53fc71b17bb1, PrivacyPolicy=accepted, KEYCLOAK_IDENTITY_LEGACY=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxNjgzNzMzNi1mMTA3LTRiMTktODk1Yi0wNWJmZDliZGIzYTUifQ.eyJleHAiOjE2MDk3ODQ0NzcsImlhdCI6MTYwOTc0ODQ3NywianRpIjoiNTQ3YmRlZGQtOGQyYy00MTJkLWJhMzYtZjkyNzAwNjlhYzQxIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6ImNlMzA5NDFmLTQwN2YtNDM0NC05MDE5LTU4ZDJmMjZlYTgzMiIsInR5cCI6IlNlcmlhbGl6ZWQtSUQiLCJzZXNzaW9uX3N0YXRlIjoiMWNjOTAzMzAtY2YzYy00NWMzLWE0NGUtNTNmYzcxYjE3YmIxIiwic3RhdGVfY2hlY2tlciI6IkZFT3psWkRScXhqREVVOGV6MFd6MU5menZGYU1jNHRzV1J4TnlrNUc5NDQifQ.YeBB6vJYZ9Z4IUXY2-og17EMRodUdeqTBTQ31pY3P1s, AUTH_SESSION_ID_LEGACY=1cc90330-cf3c-45c3-a44e-53fc71b17bb1.4c93e8da0ca1]
In keycloak-1, the user is logged in i.e. a session is shown for idp-client.
The mentioned issue was rectified once the SSL was enabled.

How do I Migrate In-Line Links to Other Work Items That Point to New Project Work Items

I've got the Azure DevOps Migration Tools setup to where it looks like everything is coming over correctly, with one exception. When in-line links to work items are brought over the link still references the old project instead of the new one. I'm assuming that I'm missing some attribute that is telling the tool to still reference the source project but I can't for the life of me find said attribute.
Example:
There are 2 projects,: "Test Source Project" and "Test Target Project"
When "Test Source Project" gets migrated to "Test Target Project" the links in "Test Target Project" still reference the original task in "Test Source Project." Below is a screenshot of what I'm referencing.
I'm expecting the link to be: https://dev.azure.com/Company/Test%20Target%20Project/_workitems/edit/75
But I'm getting https://dev.azure.com/Company/Test%20Source%20Project/_workitems/edit/75
The version I am on is 8.9 and here's my config:
{
"Version": "8.9",
"TelemetryEnableTrace": false,
"workaroundForQuerySOAPBugEnabled": false,
"Source": {
"Collection": "https://dev.azure.com/Company/",
"Project": "Test Source Project",
"ReflectedWorkItemIDFieldName": "Custom.ReflectedWorkItemId",
"AllowCrossProjectLinking": false,
"PersonalAccessToken": ""
},
"Target": {
"Collection": "https://dev.azure.com/grda365/",
"Project": "Test Target Project",
"ReflectedWorkItemIDFieldName": "Custom.ReflectedWorkItemId",
"AllowCrossProjectLinking": false,
"PersonalAccessToken": ""
},
"FieldMaps": [],
"WorkItemTypeDefinition": {
"sourceWorkItemTypeName": "targetWorkItemTypeName"
},
"GitRepoMapping": null,
"Processors": [
{
"ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.NodeStructuresMigrationConfig",
"PrefixProjectToNodes": false,
"Enabled": true,
"BasePaths": []
},
{
"ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.WorkItemMigrationConfig",
"ReplayRevisions": true,
"PrefixProjectToNodes": false,
"UpdateCreatedDate": true,
"UpdateCreatedBy": true,
"UpdateSourceReflectedId": false,
"BuildFieldTable": false,
"AppendMigrationToolSignatureFooter": false,
"QueryBit": "AND [System.WorkItemType] NOT IN ('Test Suite', 'Test Plan')",
"OrderBit": "[System.ChangedDate] desc",
"Enabled": true,
"LinkMigration": true,
"AttachmentMigration": true,
"AttachmentWorkingPath": "c:\\temp\\WorkItemAttachmentWorkingFolder\\",
"FixHtmlAttachmentLinks": false,
"SkipToFinalRevisedWorkItemType": false,
"WorkItemCreateRetryLimit": 5,
"FilterWorkItemsThatAlreadyExistInTarget": false,
"PauseAfterEachWorkItem": false,
"AttachmentMazSize": 480000000,
"CollapseRevisions": false
},
{
"ObjectType": "VstsSyncMigrator.Engine.Configuration.Processing.WorkItemQueryMigrationConfig",
"Enabled": true
}
]
}
The tool does not update inline links.
This is an implementation issue as we migrate by iterating through all of the existing work items. For integrated links we can just add links to work items that exist in the target, and it will add from both ends once the other item is added.
For example if we are migrating 1, 2, 3 and 1, 2 reference 3 then:
#1 is migrated and no links are added as #3 does not exist
#2 is migrated and no links are added as #3 does not exist
#3 is migrated and links are added to #1 and #2
At the point of adding #3 and creating the links there is no way to know which work items have inline links to any other work items.
Ideas for fixing
OK, so that's how the tool currently works, so I am imagining a fix. Ther could be an option "RefactorInlineLinks" that parsed any description that it encountered and fixed the link if it was in scope for the migration.
However this would only work as a second pass after the migration was completed and all of the work items that will exist do exist.

Azure devops - minimal code coverage pull reqeust

I have an Angular 9 project and I am trying to get the minimal code coverage working on an pull request in Azure devops conform the documentation. However the minimal code coverage isn't working, probably missing some step....
Steps to reproduce:
Create an new Angular 9 project: "ng new DefaultWebsite"
Create build pipeline and edit the karma and protractor config conform Microsoft "Build, test, and deploy JavaScript and Node.js apps" documentation
Add and "azurepipelines-coverage.yml" in the root of my project to enable the code coverage check in an pull request conform the Microsoft "Code coverage for pull requests" documentation
Disable some test in de app.spec.ts file, so the code coverage isn't 100% any more, it now is 77%. Changed the minimal code coverag in the yml file to 95% so the pull request cannot be complited conform the theory and it should give an "Coverage status check failed" error conform the Microsoft documentation.
However when the pull request is started there is an code coverage check below the 'Status' part. When the build (with unit and e2e tests) is done, there is no code coverage error which I espect te see below the 'Status' part.
Pull reqeust with code coverage check Pull reqeust build completed
When I look at the build there are test results and code coverage results.
Build test result Build code coverage result
When I look at the code coverage result I see an Line coverage of 75% which should be an minimal of 90% conform the yml-file.
Karma config file
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
const process = require('process');
process.env.CHROME_BIN = require('puppeteer').executablePath();
config.set({
basePath: '',
frameworks: ['jasmine', '#angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('#angular-devkit/build-angular/plugins/karma'),
require('karma-junit-reporter')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage'),
reports: ['html', 'lcovonly', 'text-summary', 'cobertura'],
fixWebpackSourcePaths: true
},
coverageReporter: {
type : 'html',
dir : 'coverage/'
},
junitReporter: {
outputDir: './coverage', // results will be saved as $outputDir/$browserName.xml
outputFile: 'junit.xml', // if included, results will be saved as $outputDir/$browserName/$outputFile
suite: '', // suite will become the package name attribute in xml testsuite element
useBrowserName: true, // add browser name to report and classes names
nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element
classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element
properties: {}, // key value pair of properties to add to the <properties> section of the report
xmlVersion: null // use '1' if reporting to be per SonarQube 6.2 XML format
},
reporters: ['progress', 'kjhtml','junit'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['ChromeHeadless'],
singleRun: false,
restartOnFileChange: true
});
};
Protractor config file:
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
const { JUnitXmlReporter } = require('jasmine-reporters');
process.env.CHROME_BIN = process.env.CHROME_BIN || require("puppeteer").executablePath();
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome',
chromeOptions: {
args: ["--headless", "--disable-gpu", "--window-size=1200,900"],
binary: process.env.CHROME_BIN
}
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function () { }
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
var junitReporter = new JUnitXmlReporter({
savePath: require('path').join(__dirname, './junit'),
consolidateAll: true
});
jasmine.getEnv().addReporter(junitReporter);
}
};
azurepipelines-coverage.yml
coverage:
status: #Code coverage status will be posted to pull requests based on targets defined below.
diff: #diff coverage is code coverage only for the lines changed in a pull request.
target: 95% #set this to a desired %. Default is 70%.
Azure Build pipeline steps:
"steps": [
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "npm install",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "fe47e961-9fa8-4106-8639-368c022d43ad",
"versionSpec": "1.*",
"definitionType": "task"
},
"inputs": {
"command": "install",
"workingDir": "Project\\Frontend\\DefaultWebsite",
"verbose": "false",
"customCommand": "",
"customRegistry": "useNpmrc",
"customFeed": "",
"customEndpoint": "",
"publishRegistry": "useExternalRegistry",
"publishFeed": "",
"publishPackageMetadata": "true",
"publishEndpoint": ""
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "npm custom - test ",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "fe47e961-9fa8-4106-8639-368c022d43ad",
"versionSpec": "1.*",
"definitionType": "task"
},
"inputs": {
"command": "custom",
"workingDir": "Project\\Frontend\\DefaultWebsite",
"verbose": "false",
"customCommand": "run test",
"customRegistry": "useNpmrc",
"customFeed": "",
"customEndpoint": "",
"publishRegistry": "useExternalRegistry",
"publishFeed": "",
"publishPackageMetadata": "true",
"publishEndpoint": ""
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Publish code coverage from Project\\Frontend\\DefaultWebsite\\coverage\\cobertura-coverage.xml",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "2a7ebc54-c13e-490e-81a5-d7561ab7cd97",
"versionSpec": "1.*",
"definitionType": "task"
},
"inputs": {
"codeCoverageTool": "Cobertura",
"summaryFileLocation": "Project\\Frontend\\DefaultWebsite\\coverage\\cobertura-coverage.xml",
"pathToSources": "",
"reportDirectory": "",
"additionalCodeCoverageFiles": "",
"failIfCoverageEmpty": "false"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Publish Test Results Project\\Frontend\\DefaultWebsite\\**\\junit.xml copy",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "0b0f01ed-7dde-43ff-9cbb-e48954daf9b1",
"versionSpec": "2.*",
"definitionType": "task"
},
"inputs": {
"testRunner": "JUnit",
"testResultsFiles": "Project\\Frontend\\DefaultWebsite\\**\\junit.xml",
"searchFolder": "$(System.DefaultWorkingDirectory)",
"mergeTestResults": "false",
"failTaskOnFailedTests": "false",
"testRunTitle": "",
"platform": "",
"configuration": "",
"publishRunAttachments": "true"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "npm custom - e2e",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "fe47e961-9fa8-4106-8639-368c022d43ad",
"versionSpec": "1.*",
"definitionType": "task"
},
"inputs": {
"command": "custom",
"workingDir": "Project\\Frontend\\DefaultWebsite",
"verbose": "false",
"customCommand": "run e2e",
"customRegistry": "useNpmrc",
"customFeed": "",
"customEndpoint": "",
"publishRegistry": "useExternalRegistry",
"publishFeed": "",
"publishPackageMetadata": "true",
"publishEndpoint": ""
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Publish Test Results Project\\Frontend\\DefaultWebsite\\e2e\\**\\junitresults.xml",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "0b0f01ed-7dde-43ff-9cbb-e48954daf9b1",
"versionSpec": "2.*",
"definitionType": "task"
},
"inputs": {
"testRunner": "JUnit",
"testResultsFiles": "Project\\Frontend\\DefaultWebsite\\e2e\\**\\junitresults.xml",
"searchFolder": "$(System.DefaultWorkingDirectory)",
"mergeTestResults": "false",
"failTaskOnFailedTests": "false",
"testRunTitle": "",
"platform": "",
"configuration": "",
"publishRunAttachments": "true"
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "npm custom - prodBuild",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "fe47e961-9fa8-4106-8639-368c022d43ad",
"versionSpec": "1.*",
"definitionType": "task"
},
"inputs": {
"command": "custom",
"workingDir": "Project\\Frontend\\DefaultWebsite",
"verbose": "false",
"customCommand": "run prodBuild",
"customRegistry": "useNpmrc",
"customFeed": "",
"customEndpoint": "",
"publishRegistry": "useExternalRegistry",
"publishFeed": "",
"publishPackageMetadata": "true",
"publishEndpoint": ""
}
},
{
"environment": {},
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Publish Artifact: app",
"timeoutInMinutes": 0,
"condition": "succeeded()",
"task": {
"id": "2ff763a7-ce83-4e1f-bc89-0ae63477cebe",
"versionSpec": "1.*",
"definitionType": "task"
},
"inputs": {
"PathtoPublish": "Project\\Frontend\\DefaultWebsite\\dist",
"ArtifactName": "app",
"ArtifactType": "Container",
"TargetPath": "",
"Parallel": "false",
"ParallelCount": "8",
"FileCopyOptions": ""
}
}
],

TFS 2015 Rest API - Create Build Definition

I'm trying to create a build definition in TFS using his api rest for it.
This is the microsoft docs for TFS Api Rest
I get status code 200 but...
This is what i get when I look into Tfs build definition
Anyone knows why this is happening?
Your second link provided a screenshot that a build definition with no tasks. It seems you had created a build definition successfully, but you didn't add tasks in the build definition.
Check your rest api to see whether you have "build": [] parameter with "task" in it as the following example shows:
"build": [
{
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Build solution **\\*.sln",
"task": {
"id": "71a9a2d3-a98a-4caa-96ab-affca411ecda",
"versionSpec": "*"
},
"inputs": {
"solution": "**\\*.sln",
"msbuildArgs": "",
"platform": "$(platform)",
"configuration": "$(config)",
"clean": "false",
"restoreNugetPackages": "true",
"vsLocationMethod": "version",
"vsVersion": "latest",
"vsLocation": "",
"msbuildLocationMethod": "version",
"msbuildVersion": "latest",
"msbuildArchitecture": "x86",
"msbuildLocation": "",
"logProjectEvents": "true"
}
},
{
"enabled": true,
"continueOnError": false,
"alwaysRun": false,
"displayName": "Test Assemblies **\\*test*.dll;-:**\\obj\\**",
"task": {
"id": "ef087383-ee5e-42c7-9a53-ab56c98420f9",
"versionSpec": "*"
},
"inputs": {
"testAssembly": "**\\*test*.dll;-:**\\obj\\**",
"testFiltercriteria": "",
"runSettingsFile": "",
"codeCoverageEnabled": "true",
"otherConsoleOptions": "",
"vsTestVersion": "14.0",
"pathtoCustomTestAdapters": ""
}
}
],