Which have been broken already:

https://shattered.io/

Also. NIST considers SHA-1 as obsolete since 2011.
SHA-256 is somewhat safer for now.

We have some customer projects that uses a separate user table, in these cases we usually use a stronger hash implementation:

Method SetPassword(value As %String) As %Status
{
  set i%password = ..HashPassword(value)
  return $$$OK
}

ClassMethod HashPassword(
    value As %String,
    salt As %String = "") As %String
{
  if salt = "" {
    set salt = $$$lcase(##class(%xsd.hexBinary).LogicalToXSD($System.Encryption.GenCryptRand(32)))
  }

  set hash = $$$lcase(##class(%xsd.hexBinary).LogicalToXSD($System.Encryption.PBKDF2(value, 15000, salt,256,256)))
  return $$$FormatText(hash_":"_salt)
}

Method IsPasswordMatch(plainTextPassword As %String) As %Boolean
{
  set salt = $piece(..password, ":", 2)
  return $$ConstantTimeCompare(..HashPassword(plainTextPassword, salt), ..password)

ConstantTimeCompare(a, b)
  if $length(a) '= $length(b) return 0
  for i=1:1:$length(a) {
    // Convert char to ASCII code and then to bitstring.
    set aChar = $factor($ascii($extract(a, i)))
    set bChar = $factor($ascii($extract(b, i)))
    set match = $bitlogic(aChar ^ bChar)
    set all = $bitlogic(all | match)
  }
  // 00000000 = valid
  return $bitfind(all, 1) = 0
}

UPDATE: Oh, this technique has been mentioned already, either way this sample shows why to use it.

That's gonna be quite the bump, but it's worth mentioning. Since the adoption of %Dynamic classes, you can now provide a JSON object to methods, this way you get a syntax that ressembles POJOs (Plain Old JavaScript Objects):

ClassMethod GreetAndAsk(data As %DynamicObject) As %String
{
    return $$$FormatText("Hello %1! %2", data.name, data.message)
}

// Omitted for brevity.
write ..GreatAndAsk({
  "name": "Rubens",
  "message": "How are you?"
})

This is really useful if you must provide a method with several parameters that have some sort of link between them, here's a real use-case:

/// This method implements a full-sized configuration on how to handle multipart uploads.
ClassMethod TestPOSTMultipartFileUpload() As %Status
{
  set location = %frontier.Data.Workspace_"/fixtures/uploads/multiple"
  set destination = (location_"/:KEY/:FILE_NAME:EXTENSION")

  // 512 KB
  set maxFileSize = (1024**2/0.5)

  return %frontier.Files.Upload({
    "hooks": {
      "onItemUploadSuccess": "Frontier.UnitTest.Router:WriteResultToProcessGlobal",
      "onItemUploadError": "Frontier.UnitTest.Router:WriteErrorToProcessGlobal",
      "onComplete": "Frontier.UnitTest.Router:WriteResultSummaryToProcessGlobal"
    },
    "filters": {
      "verbose": true,
      "maxFileSize": { "value": (maxFileSize), "errorTemplate": "The file :FILE_NAME exceeded the max of :VALUE bytes." },
      "extensions": ["cls", "md", "txt", "pdf"]
    },
    "destinations": {
      "file_a": { "path": (destination) },
      "file_b": { "path": (destination) },
      "file_c": { "path": (destination), "optional": true },
      "file_d": { "path": (destination), "optional": true },
      "files": {
        "path": (location_"/files/:INDEX/:FILE_NAME:EXTENSION"),
        "slots": 3,
        "filters": { "maxFileSize": 500000000 }
      }
    }
  })
}

You should never attempt to filter the list manually (using $replace). Instead of that, if you already know what item you want to fetch then you can :

Use the $listfind to retrieve the index of the matching item inside your list and $listget to to finally fetch it.

set list = $listbuild("a","b","c")

set whatIWantToFind = "c"
set index = $listfind(list, "c") // returns the index 3.
write $listget(list, index) // returns "c".

If you don't know the content on that list, you can use $listlength to get the size of the list:

 set list = $listbuild("a","b","c")

 for i=1:1:$listlength(list) {
     write $listget(list, i) // returns the current item at index i.
 }

If you want extreme performance, then I'd suggest you to go with $listnext:

set pointer = 0
set list = $listbuild("a","b","c")
while $listnext(list, pointer, item) {
   // Self-explanatory.
}

If you really want to filter the list separators, you can use $listtostring to do the opposite of $listfromstring that you used.

set list = $listbuild("a","b","c")
write $listtostring(list, "|") // "a|b|c"

Finally, you can also compare the list as whole using $listsame:

set list = $listbuild("a","b","c")
set listB = $listbuild("a", "b", "d")
set listC = $listbuild("a","b","c")

write $listsame(list, listB) // 0. False, because they're not the same.
write $listsame(list, listC) // 1. True, the values match.

You might want to try using Port. It was made exactly for that purpose.

Just install the port-prod.xml and restart your Studio, note that this tool will takeover your current source control class.

After that, open your project, Source Control->Export. If your language is not supported, then you might need to change your current session to english using ##class(%MessageDictionary).SetSessionLanguage("en").

@Eduard Lebedyuk no, this is a misconception. In a nutshell CORS is the opposite, by default every green browser will apply the Same Origin Policy to allow or negate the access. However CORS has been made for making that policy lax (since it allow you to access a resource outside the origin's domain). 

Needless to say, this wouldn't prevent the attacker from GET'ing a resource because GET methods don't execute a pre-flight request, and that's just the tip of the iceberg, you can read more about it here:

About the misconception https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2017/september/common-csrf-prevention-misconceptions/

About the correct implementation https://www.acunetix.com/websitesecurity/csrf-attacks/

Btw, this implementation doesn't validate the token, neither it generates something randomically strong (using CPRNG). Checking if the header is present  is not enough. OWASP advises you to generate tokens that you can validate. It also suggests that the implementation should use stateful URLs, like the ones containing the token themselves (which is similar to the CSPToken that each private CSP page has).

That's the issue. You can't read any new environment variables after the Caché/Ensemble process (by that I meant at OS level, using a shell script) has been started. Not even Docker allows you to do that, since you must rebuild the container to "refresh" the variables. Otherwise that would be a security flaw as @Stefano Cairoli pointed out.

If you own the code, you can try simulating env variables by using globals, which is exactly the same thing the class Sample.Installer does or populate it from an external file, like a .env. Also $zf won't work because it always summons a new shell to execute your call, so even though the variables you set would be available there, it won't be there for your current process (again, OS level).

Are you trying to execute some binary outside Caché or is it related to your current Caché process? By the type of the value you used as example, I'm attempted to say it's related to the JVM. If so, you can set most of the values using the its command-line arguments, including the heap size.

If that's related to your current process, you could trying doing the inverse procedure and capture the values from a .env file instead, it seems you can't get freshly set env variables because for the OS the Caché is already a running process. Maybe you can work around it using by source 'ing a script file that sets it, but I haven't tried.

However, I'd still go with the .env file instead. I did a little utility sometime ago because I thought it would be useful someday

It actually works and it can even transport objects using %session.Data, it also seems to run in a separate process from the request, which means a non-blocking operation. But I could  only make it work by defining the event class on the web application config even though there's a way to define it dynamically by using %session.EventClass.

So my only question is: Is there a moment for setting this up? Like when using OnPreHTTP for %response? I tried setting it using the classmethod Page after calling the superclass (%CSP.REST) but no avail. And %CSP.REST doesn't provide OnPreHTTP because it overwrites the Page method completely.

Now regarding the data we can retrieve from the default %CSP.REST implementation is none.  As we only have access to %session and %request (I didn't tried %response), it lacks any metadata that is used for %CSP.REST based applications (dispatch method, dispatch class, route arguments, stack, etc) since no object is created for it.

 

That means you still need a way to retrieve this info, this is why I had to transport the object over by using %session.Data. And here's how I did it:

ClassMethod Page(skipheader As %Boolean = 1) As %Status [ ProcedureBlock = 0 ]
{
  new %frontier
  set %frontier = ##class(Frontier.Context).%New(%session, %request, %response)
  set %session.Data("%frontier") = %frontier
  $$$QuitOnError(##super(skipheader))
  return $$$OK
}

And the event class:

/// Called when we have finished processing this request
ClassMethod OnEndRequest() As %Status
{
  set frontier = %session.Data("%frontier")
  return frontier.ReporterManager.Report()
}

Now using %CSP.REST I think the best approach is to create an utility method that is called on the beginning of each dispatch method. This utility would populate %session.Data with context sensitive info like arguments received. This method must be called for each method that is dispatchable. An example:

ClassMethod PopulateLogObject(arguments As %List, method, classname)
{
    set log = ##class(MyApp.Log).%New()
    set log.username = $username // <--  This is the only one you can fetch directly when using %CSP.SessionEvents.
    set log.parameters = arguments
    set log.method = method
    set log.classname = $classname()
    return log.%Save()
}

ClassMethod DoSomethingRequestedOverHTTP(argA, argB, argC)
{
     try {
        $$$ThrowOnError(..PopulateLogObject($lb(argA, argB, argC), "DoSomethingRequestedOverHTTP", $classname())

     } catch e {
        // render error response.
     }
    // render success response.
}

I don't know of any other possible way from getting this kind of info, unless if you overwrite DispatchRequest from %CSP.REST.

No, you can't. Unless you ovewrite some methods from %CSP.REST, like DispatchMethod.
 

Even so, simply ovewritting it wouldn't give you data about arguments that your dispatch method received, you need to go further than that and modify the way the info about the route is generated.

I also had headaches with that, because the pattern generation algorithm simply replaces any :placeholder by it's regular expression group counterpart, e.g. for Route elements /:msg becomes /([^/]+), but there're some variations according to which element you use to define it: Map or Route.

When compile your class, a method generator runs and creates a DispatchMap that takes an index, this index contains info about your dispatch method, http method and pattern to match. This index is based on the order you defined each element.

However DispatchMap does not generate info about the name of the parameter affected, only their index, so you would need to parse it by opening the dispatch method's class %Dictionary.CompiledMethod and accessing each Property's FormalSpec and matching their index to find the name of the argument.

This is some of the reasons why I implemented this, because I found %CSP.REST very limited. And what you want is something that I call: Reporter. It's a an abstract module that runs custom implementations whenever a method ends abnormally. I already implemented a sample of it for reporting an error via e-mail. 

EDIT: I just noticed that you want something to run for every request, regardless of success or error. I'll work on it.

You must notice two methods as declared here. These are the methods that should be implemented.  After that you only need to register the setup class with your router class. If you want to see it quickly, just change the commented reporter to this one and configure your e-mail parameters.

Finally, you can use %OAuth2's JWT implementation to store info about your current user. I'd recommend you to read this tutorial to learn how to setup it.

And if you want to read more about how my implementation works, you can find it out here.

No, you need to grant the group/user you're using for Caché permission to access the executable that's being denied.
On Windows, Caché uses the same user that started the process. Remember that you're trying to access a resource natively from your OS, so your Caché user is NOT what you should check.

 

If you need to know which you should be looking for, open a cmd and type "whoami".

Now you'll need to have an account with Administrator privileges, otherwise you won't be able to edit your executable's permissions. If you're working in company network, then your user probably wont have enough privileges for changing that file's permissions, so I'd recommend leaving this task for your IT technician.

 

The technician should know what to do,  just ask him to add your user to list of groups/users that are allowed to execute your file. Normally you would only need "read and execute", unless that executable also generates some file somewhere, so also grant your user the permission to write.

There's no embedded or native way of doing so, due to, well... security concerns.

There're scripts and third party programs that allow you to do something close to it.

https://stackoverflow.com/questions/19098101/how-to-open-an-elevated-cmd...

However, should you really be executing it with admin privileges? Why not make your executable accessible for your Caché user, so that you won't need to elevate your prompt?

Implementing IntelliSense seems to require a major overhaul of the current extension as it requires the usage of a language server and a language client that sends and retrieves a lot of essential metadata for code diagnostics. Some of that I don't know if InterSystems publicly discloses.

A brief protocol explanation: https://code.visualstudio.com/blogs/2016/06/27/common-language-protocol
The full protocol: https://github.com/Microsoft/language-server-protocol/blob/master/protoc...

The implementation using NodeJS: https://github.com/Microsoft/vscode-languageserver-node

On the last repository you will notice that it actually contains the JSONRPC 2.0 message definition, the protocol, and finally the base server and client implementations.

Hello Daniel, I'm trying to figure how to make a REST resource available through JWT access token.

I noticed that you used:

set accessToken=##class(%SYS.OAuth2.AccessToken).GetAccessTokenFromRequest(.sc)


For your resource oauth2test.demoResource, but it doesn't seem like this method validates the access token itself.
As it only checks for http header validity.

Does this means I'm obligated to call the introspection method or should I simply use:

##class(%SYS.OAuth2.Validation).ValidateJWT(..#OAUTH2APPNAME,accessToken,"scope1 scope2",,.jsonObject,.securityParameters,.sc)

Any help regarding this doubt is appreciated.