Hi,
I’m trying to configure dynamic multi-select Custom Picker field “Hyp. Mitre Techniques“. Values show by that field should depend on value from multi-select Custom Picker field “Hyp. Mitre Tactics“.
“Hyp. Mitre Tactics“ is developed and working fine. I can’t read value of this field in my script for “Hyp. Mitre Techniques“. I’m trying to do it following way
import com.atlassian.jira.issue.Issue
Issue issue
def mitre_tactic = issue.getCustomFieldValue("Hyp. Mitre Tactics")
java.lang.NullPointerException: Cannot invoke method getCustomFieldValue() on null object at Script285.run(Script285.groovy:6)
How can I get value of other field in Custom Picker?
Here is my code for both fields
Hyp. Mitre Tactics
import com.onresolve.scriptrunner.canned.jira.fields.model.PickerOption
import org.apache.commons.lang3.StringUtils
def options = [
[tactic: "TA0001 Initial Access"],
[tactic: "TA0002 Execution"],
[tactic: "TA0003 Persistence"],
[tactic: "TA0004 Privilege Escalation"],
[tactic: "TA0005 Defense Evasion"],
[tactic: "TA0006 Credential Access"],
[tactic: "TA0007 Discovery"],
[tactic: "TA0008 Lateral Movement"],
[tactic: "TA0009 Collection"],
[tactic: "TA0010 Exfiltration"],
[tactic: "TA0011 Command and Control"],
[tactic: "TA0040 Impact"],
[tactic: "TA0042 Resource Development"],
[tactic: "TA0043 Reconnaissance"]
]
search = { String inputValue ->
options.findAll {
StringUtils.containsIgnoreCase(it.tactic, inputValue)
}
}
getItemFromId = { String id ->
options.find { it.tactic == id }
}
toOption = { Map<String, String> option, Closure highlight ->
new PickerOption(value: option.tactic,
html: "${highlight(option.tactic, false)}"
)
}
renderItemViewHtml = { Map<String, String> option ->
"$option.tactic"
}
renderItemTextOnlyValue = { Map<String, String> option ->
option.id
}
import com.onresolve.scriptrunner.canned.jira.fields.model.PickerOption
import org.apache.commons.lang3.StringUtils
import com.atlassian.jira.issue.Issue
Issue issue
def mitre_tactic = issue.getCustomFieldValue("Hyp. Mitre Tactics")
def picker_options = [
"TA0011 Command and Control": [
[technique: "T1001 Data Obfuscation"],
[technique: "T1008 Fallback Channels"],
[technique: "T1071 Application Layer Protocol"],
[technique: "T1090 Proxy"],
[technique: "T1092 Communication Through Removable Media"],
[technique: "T1095 Non-Application Layer Protocol"],
[technique: "T1102 Web Service"],
[technique: "T1104 Multi-Stage Channels"],
[technique: "T1105 Ingress Tool Transfer"],
[technique: "T1132 Data Encoding"],
[technique: "T1205 Traffic Signaling"],
[technique: "T1219 Remote Access Software"],
[technique: "T1568 Dynamic Resolution"],
[technique: "T1571 Non-Standard Port"],
[technique: "T1572 Protocol Tunneling"],
[technique: "TT1573 Encrypted Channel"]
],
"TA0006 Credential Access": [
[technique: "T1003 OS Credential Dumping"],
[technique: "T1040 Network Sniffing"],
[technique: "T1056 Input Capture"],
[technique: "T1110 Brute Force"],
[technique: "T1111 Multi-Factor Authentication Interception"],
[technique: "T1187 Forced Authentication"],
[technique: "T1212 Exploitation for Credential Access"],
[technique: "T1528 Steal Application Access Token"],
[technique: "T1539 Steal Web Session Cookie"],
[technique: "T1552 Unsecured Credentials"],
[technique: "T1555 Credentials from Password Stores"],
[technique: "T1556 Modify Authentication Process"],
[technique: "T1557 Adversary-in-the-Middle"],
[technique: "T1558 Steal or Forge Kerberos Tickets"],
[technique: "T1606 Forge Web Credentials"],
[technique: "T1621 Multi-Factor Authentication Request Generation"]
]
]
def options = []
for (tactic in mitre_tactic){
def tactic_options = picker_options.get(tactic)
options.addAll(tactic_options)
}
search = { String inputValue ->
options.findAll {
StringUtils.containsIgnoreCase(it.technique, inputValue)
}
}
getItemFromId = { String id ->
options.find { it.technique == id }
}
toOption = { Map<String, String> option, Closure highlight ->
new PickerOption(value: option.technique,
html: "${highlight(option.technique, false)}"
)
}
renderItemViewHtml = { Map<String, String> option ->
"$option.technique"
}
renderItemTextOnlyValue = { Map<String, String> option ->
option.id
}
I resolved my problem. I had to define issue in inputs for search function and in getItemFromId function I had to provide list of all possible options. After that I was able to read field value inside that functions.
I created additional technique_searcher function to prepare filtered options list for "search" function and all options list for "getItemFromId" function
In the context of ScriptRunner, you use issue directly, you don't need to define it. remove this definition
Issue issue
and use something like below
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def tacticField = customFieldManager.getCustomFieldObjectByName("Hyp. Mitre Tactics")
def mitre_tactic = issue?.getCustomFieldValue(tacticField)
if (!mitre_tactic) {
mitre_tactic = []
}
...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I tried to do it like that but it shows that "issue" is undeclared
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Did you try to run it? Sometimes the editor shows compile errors but it may run ok.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yes i tried. I returns following error
groovy.lang.MissingPropertyException: No such property: issue for class: Script269 at Script269.run(Script269.groovy:12)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.